編輯:關於Android編程
由於不是系統級的應用, 也沒有獲得ROOT權限, 所以自己實現任務管理器其實意義並不是很大, 就像沒有root的手機安裝了LBE這類的手機助手, 雖然也帶一鍵清理內存清理後台進程的功能, 但由於手機助手沒有ROOT的最高權限, 因此面對開啟了守護進程或者其他自啟動的應用進程也是手無舉措. 而隨著谷歌的推動, 即將推送面世的新系統Android M, 也對權限的管理越來越嚴格, 這也看出一個趨勢, 對移動系統的安全和穩定性要求是越來越高.
雖然意義並不是很大, 但我們還是來練練手吧, 說不定哪天就用上了呢... 哈哈哈.
(效果圖)
API是直接提供獲取包信息, 應用進程信息以及關閉後台進程等接口的. 思路大概是, 首先獲取所有正在運行的進程, 包括系統應用進程和非系統應用進程. 為了防止誤關系統進程而引起的錯誤, 我們過濾掉系統進程, 只在列表顯示非系統進程. 然後根據進程的包名, 可以實現關閉正在運行的某個進程或所有進程.
但這裡通過這裡的例子, 發現關閉了比如微信這樣的軟件, 但很快又在後台重新創建線程繼續運行, 所以做的再好的第三方手機助手應用, 只要這個應用程序沒有獲取root權限或者系統權限, 依然是無法徹底關閉進程或者防止自啟的. 就算加入了類似鎖屏自動清後台, 一鍵清理內存等等這樣的功能, 沒有root權限的普通應用只能通過類似守護進程的方式, 維持本應用的生命力, 然後每隔一段時間就清一次後台進程. 也額外的耗一點電. 當然這好不好, 就看後台一個應用程序能不能殺掉眾多第三方後台應用而比原來更節電, 見仁見智吧哈.
實現的過程, 並沒有什麼困難的地方, 所以就直接上代碼了:
首先是ListView的item布局文件 process_list_item.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; } }
/** * Created by AlexTam on 2015/7/29. */ public class ProcessListAdapter extends BaseAdapter{ private Context context; private ListprocessList; 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); } }
/** * Created by AlexTam on 2015/7/29. */ public class MainActivity extends Activity { private ListView ll_main; private ListprocessList = 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(); } }
相信很多人都明白, 其實Android系統有自己的運行機制, 每個應用都有自己的進程, 每個進程對應有一個虛擬機, 這樣設計為的是當自己這個進程掛掉也不會影響系統的運行和其他進程. 而當運行一些比較占內存的應用時, 系統也會自動將優先級低, 視為無用,過時的後台進程關閉, 從而擠出內存. 當然這不是萬能的, 因為系統也並不總是能這麼及時的處理, 以至於我們在使用比如游戲這樣的應用時, 低內存的手機還是會由於內存不足的原因感覺有些卡頓. 所以顯得手動請後台有一定的合理性.
最近的項目,有個需求需要使用條狀圖顯示比例,並且右對齊,見下圖: 我想到了使用進度條,這樣不就不需要在代碼動態繪制條狀了,省了很多活。 那麼進度條怎樣從右向左顯示呢?
前幾天完成了一個客戶端小功能,使用html頁面登錄, 拿到cookie之後,傳遞給httpclient完成業務邏輯的訪問,現在把基本的流程整理記錄一下。 首先來一張a
MainActivity:package com.ruru.dialogproject; import android.app.Activity; import andr
前言 本文主要介紹在Android中怎樣來解析XML文件。主要采用的是SAX機制,SAX全稱為Simple API for XML,它既是一種接口,也是一個