Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android]實現簡單的任務管理器(非root)

[Android]實現簡單的任務管理器(非root)

編輯:關於Android編程

由於不是系統級的應用, 也沒有獲得ROOT權限, 所以自己實現任務管理器其實意義並不是很大, 就像沒有root的手機安裝了LBE這類的手機助手, 雖然也帶一鍵清理內存清理後台進程的功能, 但由於手機助手沒有ROOT的最高權限, 因此面對開啟了守護進程或者其他自啟動的應用進程也是手無舉措. 而隨著谷歌的推動, 即將推送面世的新系統Android M, 也對權限的管理越來越嚴格, 這也看出一個趨勢, 對移動系統的安全和穩定性要求是越來越高.

 

雖然意義並不是很大, 但我們還是來練練手吧, 說不定哪天就用上了呢... 哈哈哈.

(效果圖)

\

 

API是直接提供獲取包信息, 應用進程信息以及關閉後台進程等接口的. 思路大概是, 首先獲取所有正在運行的進程, 包括系統應用進程和非系統應用進程. 為了防止誤關系統進程而引起的錯誤, 我們過濾掉系統進程, 只在列表顯示非系統進程. 然後根據進程的包名, 可以實現關閉正在運行的某個進程或所有進程.

 

但這裡通過這裡的例子, 發現關閉了比如微信這樣的軟件, 但很快又在後台重新創建線程繼續運行, 所以做的再好的第三方手機助手應用, 只要這個應用程序沒有獲取root權限或者系統權限, 依然是無法徹底關閉進程或者防止自啟的. 就算加入了類似鎖屏自動清後台, 一鍵清理內存等等這樣的功能, 沒有root權限的普通應用只能通過類似守護進程的方式, 維持本應用的生命力, 然後每隔一段時間就清一次後台進程. 也額外的耗一點電. 當然這好不好, 就看後台一個應用程序能不能殺掉眾多第三方後台應用而比原來更節電, 見仁見智吧哈.

 

實現的過程, 並沒有什麼困難的地方, 所以就直接上代碼了:

首先是ListView的item布局文件 process_list_item.xml :

 



    

    

    

然後是主類布局文件 activity_main.xml :

 

 



    

 

進程信息對象 ProcessInfo :

 

/**
 * Created by AlexTam on 2015/7/29.
 */
public class ProcessInfo {
    private String labelName;
    private Drawable labelIcon;
    private String processName;

    public ProcessInfo(){ }

    public ProcessInfo(String labelName, Drawable labelIcon, String processName) {
        this.labelName = labelName;
        this.labelIcon = labelIcon;
        this.processName = processName;
    }

    public String getLabelName() {
        return labelName;
    }

    public void setLabelName(String labelName) {
        this.labelName = labelName;
    }

    public Drawable getLabelIcon() {
        return labelIcon;
    }

    public void setLabelIcon(Drawable labelIcon) {
        this.labelIcon = labelIcon;
    }

    public String getProcessName() {
        return processName;
    }

    public void setProcessName(String processName) {
        this.processName = processName;
    }
}

然後是Adapter, 裡面給每個item的按鈕都添加點擊事件 :

 

 

/**
 * Created by AlexTam on 2015/7/29.
 */
public class ProcessListAdapter extends BaseAdapter{
    private Context context;
    private List processList;
    private viewHolder holder;
    private processListButtonClick listener;


    public ProcessListAdapter(Context context, List processList,
            processListButtonClick listener)
    {
        this.context = context;
        this.processList = processList;
        this.listener = listener;
    }

    @Override
    public int getCount() {
        return processList.size();
    }

    @Override
    public Object getItem(int position) {
        return processList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ProcessInfo processInfo = (ProcessInfo)getItem(position);

        if(convertView == null)
        {
            holder = new viewHolder();
            convertView = View.inflate(context, R.layout.process_list_item, null);
            holder.imv_avatar = (ImageView) convertView.findViewById(R.id.imv_avatar);
            holder.tv_name = (TextView) convertView.findViewById(R.id.tv_app_name);
            holder.tv_processName = (TextView) convertView.findViewById(R.id.tv_app_process_name);
            holder.btn = (Button) convertView.findViewById(R.id.btn_stop_app);
        }
        else
        {
            holder = (viewHolder)convertView.getTag();
        }

        holder.imv_avatar.setImageDrawable(processInfo.getLabelIcon());
        holder.tv_name.setText(processInfo.getLabelName());
        holder.tv_processName.setText(processInfo.getProcessName());
        holder.btn.setOnClickListener(new POnClickListener(processInfo.getProcessName()));

        convertView.setTag(holder);

        return convertView;
    }

    private class POnClickListener implements View.OnClickListener
    {
        private String processName;

        public POnClickListener(String processName)
        {
            this.processName = processName;
        }

        @Override
        public void onClick(View v)
        {
            if(listener != null)
                listener.onButtonClick(processName);
        }
    }

    private class viewHolder
    {
        ImageView imv_avatar;
        TextView tv_name;
        TextView tv_processName;
        Button btn;
    }

    public interface processListButtonClick
    {
        void onButtonClick(String processName);
    }

}

OK, 最後是主類 MainActivity :

 

 

/**
 * Created by AlexTam on 2015/7/29.
 */
public class MainActivity extends Activity {
    private ListView ll_main;

    private List processList
            = new ArrayList();
    private List applicationInfoList ;

    private ProcessListAdapter adapter = null;

    private Button btn_clear;

    private List processNamelist = new ArrayList();

    private ProgressDialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ll_main = (ListView) findViewById(R.id.lv_main);
        btn_clear = (Button) findViewById(R.id.btn_main_clear);

        getProcessList();

        btn_clear.setOnClickListener(new MyOnclick());
    }


    @Override
    public void onDestroy()
    {
        super.onDestroy();
    }


    private class MyOnclick implements View.OnClickListener
    {
        @Override
        public void onClick(View v)
        {
            if(v == btn_clear)
            {
                clearAllBackgroundProcess();
            }
        }
    }


    /**
     * 獲取進程信息列表
     */
    private void getProcessList()
    {
        ActivityManager activityManager
                = (ActivityManager)getSystemService(ACTIVITY_SERVICE);

        //獲取所有將運行中的進程
        List runningAppList
                = activityManager.getRunningAppProcesses();

        PackageManager packageManager
                = this.getPackageManager();

        //獲取所有包信息
        applicationInfoList
                = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);


        if(processList != null && processList.size() > 0)
            processList.clear();

        if(processNamelist != null && processNamelist.size() > 0)
            processNamelist.clear();

        for(ActivityManager.RunningAppProcessInfo process : runningAppList)
        {
            if(process.processName.indexOf(this.getPackageName()) < 0)
            {   //過濾本應用包名
                ProcessInfo p = new ProcessInfo();

                ApplicationInfo appInfo = getApplicationInfoByProcessName(process.processName);
                if(appInfo == null)
                {
                    //有些應用的守護進程並沒有目標應用對應,此時返回null
                }
                else
                {
                    p.setLabelIcon(appInfo.loadIcon(packageManager));
                    p.setLabelName(appInfo.loadLabel(packageManager).toString());
                    p.setProcessName(appInfo.processName);

                    processNamelist.add(appInfo.processName);
                    processList.add(p);
                }
            }
        }

        if(adapter == null)
        {
            adapter = new ProcessListAdapter(MainActivity.this, processList,new ItemButtonClick());
            ll_main.setAdapter(adapter);
            ll_main.setOnItemClickListener(new MyOnItemClickListener());
        }
        else
        {
            adapter.notifyDataSetChanged();
        }

    }

    /**
     * 根據進程名獲取應用信息
     * @param processNames
     * @return
     */
    private ApplicationInfo getApplicationInfoByProcessName(String processNames)
    {
        if(applicationInfoList == null || applicationInfoList.size() < 1)
            return null;

        for(ApplicationInfo applicationInfo : applicationInfoList)
        {
            if(applicationInfo.processName.equals(processNames)
                    && (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0)
                //只顯示第三方的應用進程,不顯示系統應用
                //要顯示所有應用進程,刪去(applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0 即可
                return applicationInfo;
        }
        return null;
    }

    private class MyOnItemClickListener implements AdapterView.OnItemClickListener
    {
        @Override
        public void onItemClick(AdapterView parent, View view, int position, long id)
        {
            TextView tv_appName = (TextView) view.findViewById(R.id.tv_app_name);
            TextView tv_processName = (TextView) view.findViewById(R.id.tv_app_process_name);

            String appName = tv_appName.getText().toString();
            String processName = tv_processName.getText().toString();

            Toast.makeText(MainActivity.this, 應用:  + appName + 
進程:  + processName,
                    Toast.LENGTH_SHORT).show();
        }
    }

    private class ItemButtonClick implements ProcessListAdapter.processListButtonClick
    {
        String pName = null;

        @Override
        public void onButtonClick(String processName) {
            pName = processName;

            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle(關閉進程)
                    .setMessage(確定要關閉  + processName+ 進程嗎?)
                    .setPositiveButton(確定, new DialogInterface.OnClickListener(){
                        public void onClick(DialogInterface dialog, int which)
                        {
                            if(pName != null)
                            {
                                ActivityManager activityManager
                                        = (ActivityManager)MainActivity.this.
                                        getSystemService(ACTIVITY_SERVICE);

                                activityManager.killBackgroundProcesses(pName);
                                getProcessList();
                            }
                        }
                    })
                    .setNegativeButton(取消, new DialogInterface.OnClickListener(){
                        public void onClick(DialogInterface dialog, int which)
                        {
                            dialog.dismiss();
                        }
                    });

            builder.show();
        }
    }


    private Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            if(msg.what == 0x1)
            {
                startClearAnim();
            }
            else if(msg.what == 0x2)
            {
                stopClearAnim();
                getProcessList();
            }
            super.handleMessage(msg);
        }
    };


    /**
     * 一鍵清理
     */
    private void clearAllBackgroundProcess()
    {
        mHandler.sendEmptyMessage(0x1);

        ActivityManager activityManager
                = (ActivityManager)MainActivity.this.getSystemService(ACTIVITY_SERVICE);

        if(processNamelist != null && processNamelist.size() > 0)
        {
            for(String processName : processNamelist)
            {
                activityManager.killBackgroundProcesses(processName);
            }
        }
        mHandler.sendEmptyMessageDelayed(0x2, 2000);
    }

    private void startClearAnim()
    {
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage(努力清理中...);
        progressDialog.show();
    }

    private void stopClearAnim()
    {
        progressDialog.dismiss();
    }


}

因為是探討功能, 一鍵清理並沒有加入復雜的動畫. 如果要加入, 可以考慮在視圖中間隱藏一個ImageView, 然後用AnimatorSet存放兩個屬性動畫去實現, 一個是控制ImageView從透明到完全顯示, 同時大小也是從0.0f 到1.0f . 第二個是控制無限的旋轉. 當然, 用Animation也能實現, 一樣的哈. 最後當清理完成, 就再次隱藏ImageView, 設為gone. 至於那些將快捷方式放到手機桌面, 然後點擊快捷方式組件就有個動畫出來, 同時清理後台的, 可以考慮做一個Activity, theme為一個dialog, 然後播放動畫同時清理後台. 也能達到類似的效果.

 

 

相信很多人都明白, 其實Android系統有自己的運行機制, 每個應用都有自己的進程, 每個進程對應有一個虛擬機, 這樣設計為的是當自己這個進程掛掉也不會影響系統的運行和其他進程. 而當運行一些比較占內存的應用時, 系統也會自動將優先級低, 視為無用,過時的後台進程關閉, 從而擠出內存. 當然這不是萬能的, 因為系統也並不總是能這麼及時的處理, 以至於我們在使用比如游戲這樣的應用時, 低內存的手機還是會由於內存不足的原因感覺有些卡頓. 所以顯得手動請後台有一定的合理性.

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved