[Android]實現簡單的工作管理員(非root)

來源:互聯網
上載者:User

[Android]實現簡單的工作管理員(非root)

由於不是系統級的應用, 也沒有獲得ROOT許可權, 所以自己實現工作管理員其實意義並不是很大, 就像沒有root的手機安裝了LBE這類的手機小幫手, 雖然也帶一鍵清理記憶體清理後台進程的功能, 但由於手機小幫手沒有ROOT的最高許可權, 因此面對開啟了守護進程或者其他自啟動的應用進程也是手無舉措. 而隨著Google的推動, 即將推送面世的新系統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系統有自己的運行機制, 每個應用都有自己的進程, 每個進程對應有一個虛擬機器, 這樣設計為的是當自己這個進程掛掉也不會影響系統的運行和其他進程. 而當運行一些比較占記憶體的應用時, 系統也會自動將優先順序低, 視為無用,過時的後台進程關閉, 從而擠出記憶體. 當然這不是萬能的, 因為系統也並不總是能這麼及時的處理, 以至於我們在使用比如遊戲這樣的應用時, 低記憶體的手機還是會由於記憶體不足的原因感覺有些卡頓. 所以顯得手動請後台有一定的合理性.

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.