本文主要是介绍Android项目实战--手机卫士29--杀死后台进程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最新实战教程,让你了解Android自动化刷量、作弊与防作弊的那些事,案例:刷友盟统计、批量注册苹果帐号
昨天,我们就已经把那些进程给读取出来,然后再显示到界面上的啦,那么今天,我们就要做一个功能,那就是把进程杀死,达到我们的一键清理的功能
但是在做这个杀死进程的功能之前,我们先来修复一个bug先,大家先看下面的一张图
细心的朋友们可能就会看到的啦,我们在title上面的进程数目显示的是16个,但是在下面的用户进程和系统进程加起来也就只有13个,竟然会少了三个,那是为什么呢
其实,那少了的三个是因为,它是没有界面的,而且是没有对应的ApplicationInfo对象的,所以当我们通过包名来获取到相应的ApplicationInfo对象的时候,就会报错的啦
因为我们try catch了,所以我们的应用才不会挂掉。
那么我们今天就对这些特殊情况进程处理一下就可以的啦,我们就在catch块里面,把它的包名就设置成应用的名字就行啦,然后再给它加一个默认的图标
catch (Exception e){e.printStackTrace();//当遇到没有界面的和图标的一些进程时候的处理方式taskInfo.setName(packageName);taskInfo.setSystemProcess(true);taskInfo.setIcon(defaultIcon);}
下面就是完整的,修改后的类
com.xiaobin.security.engine.TaskInfoProvider
package com.xiaobin.security.engine;import java.util.ArrayList;
import java.util.List;import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Debug.MemoryInfo;import com.xiaobin.security.R;
import com.xiaobin.security.domain.TaskInfo;public class TaskInfoProvider
{private PackageManager packageManager;private ActivityManager activityManager;private Drawable defaultIcon;public TaskInfoProvider(Context context){defaultIcon = context.getResources().getDrawable(R.drawable.ic_launcher);packageManager = context.getPackageManager();activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);}public List<TaskInfo> getAllTask(List<RunningAppProcessInfo> runningAppProcessInfos){List<TaskInfo> taskInfos = new ArrayList<TaskInfo>();for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcessInfos){TaskInfo taskInfo = new TaskInfo();int id = runningAppProcessInfo.pid;taskInfo.setId(id);String packageName = runningAppProcessInfo.processName;taskInfo.setPackageName(packageName);try{// ApplicationInfo是AndroidMainfest文件里面整个Application节点的封装ApplicationInfo applicationInfo = packageManager.getPackageInfo(packageName, 0).applicationInfo;// 应用的图标Drawable icon = applicationInfo.loadIcon(packageManager);taskInfo.setIcon(icon);// 应用的名字String name = applicationInfo.loadLabel(packageManager).toString();taskInfo.setName(name);// 设置是否为系统应用taskInfo.setSystemProcess(!filterApp(applicationInfo));}catch (Exception e){e.printStackTrace();//当遇到没有界面的和图标的一些进程时候的处理方式taskInfo.setName(packageName);taskInfo.setSystemProcess(true);taskInfo.setIcon(defaultIcon);}// 可以返回一个内存信息的数组,传进去的id有多少个,就返回多少个对应id的内存信息MemoryInfo[] memoryInfos = activityManager.getProcessMemoryInfo(new int[] { id });// 拿到占用的内存空间int memory = memoryInfos[0].getTotalPrivateDirty();taskInfo.setMemory(memory);taskInfos.add(taskInfo);taskInfo = null;}return taskInfos;}// 判断某一个应用程序是不是用户的应用程序,如果是返回true,否则返回falsepublic boolean filterApp(ApplicationInfo info){// 有些系统应用是可以更新的,如果用户自己下载了一个系统的应用来更新了原来的,// 它就不是系统应用啦,这个就是判断这种情况的if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0){return true;}else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0)// 判断是不是系统应用{return true;}return false;}}
好啦,就 这样子,我们的这个bug就修复好的啦,大家可以测试一下,这一次拿到的进程数目就会和title上显示的是一致的啦
那么我们现在就可以来完成我们的杀死后台进程的这个功能啦,这个功能也是非常容易完成的,但在这之前,我们要先来处理一下我们的那个checkbox才行
因为我们是通过点击listview的item来进行选定,然后修改checkbox的状态的,但是现在,我们是无法点击listview里面的item的,因为焦点被checkbox抢过去啦
所以我们要在checkbox的布局文件里面指定两个属性
<CheckBox android:id="@+id/cb_process_manager_state"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="10dip"android:focusable="false"android:clickable="false"/>
我们把它的focusable和clickable都设置为false,这样子,它就无法抢夺listview的焦点的啦
那么,我们就可以来完成我们的杀死后台进程的操作啦,首先,我们就先把给我们的listview添加一个点击事件啦
lv_process_list.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id){// adapter里面的getItem返回的值Object obj = lv_process_list.getItemAtPosition(position);if (obj instanceof TaskInfo){cb_process_state = (CheckBox) view.findViewById(R.id.cb_process_manager_state);TaskInfo taskInfo = (TaskInfo) obj;if (taskInfo.isCheck()){taskInfo.setCheck(false);cb_process_state.setChecked(false);}else{taskInfo.setCheck(true);cb_process_state.setChecked(true);}}}});
首先,我们是会拿到我们所点击的条目所对应的那个对象啦,也就是adapter里面getItem所返回的对象啦,所以我们就判断一下,当它是TaskInfo类型的,那么就进行处理啦
为什么要这样子判断呢,那是因为我们有两个标签的嘛,它们也是会返回的,所以就要进行判断啦,如果点击所对应的对象是TaskInfo的对象,那么就根据它的check状态来设置checkbox的状态啦。
这样子,我们通过点击,就能设置好checkbox的状态啦,那么接下来,我们就要根据checkbox的状态,把那些选定了的进程给杀死
其实这个杀死后台进程也是非常简单的,只需要调用activityManager里面的一个方法就可以的啦,但我们麻烦的就是要刷新界面,所以我们写了一个方法
// 一键清理的函数private void killTask(){int total = 0;int memorySize = 0;for (TaskInfo taskInfo : systemTaskInfos){if(taskInfo.isCheck()){// 杀死进程activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}for (TaskInfo taskInfo : userTaskInfos){if(taskInfo.isCheck()){activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}Toast.makeText(this,"已经杀死了" + total + "个进程!释放了"+ TextFormater.getSizeFromKB(memorySize) + "空间",Toast.LENGTH_SHORT).show();//重新加载界面adapter = new TaskInfoAdapter();lv_process_list.setAdapter(adapter);}
大家可以看到,杀死进程,就是调用了ActivityManager里面的一个方法killBackgroundProcesses,传递进去的是一个包名
因为我们要刷新界面嘛,而我们的界面是通过我们的list集合里面的数据进行显示的,所以我们就把用户进程和系统进程这两个集合做成了类的变量,然后遍历这两个集合
如果是选定了的,就杀死对应的进程,并移除掉这个对象,并累计杀死的进程数目与释放的内存空间,最后就是重新new一个adapter出来,然后刷新界面
在这里,我要和大家说一下,这个杀死进程,其实并不是真的可以把进程杀死的,其实有一些重要的进程,你一杀死它,它就会马上再开启的,所以并不可能杀死了,后台就没有的啦,大家要清楚认识到这一点
好啦,讲到这里,我们把后台进程干掉的功能也完成的啦,下一次我们就把一些小问题修复一下,如那个title的更新,下面把完成的activity粘出来
com.xiaobin.security.ui.ProcessManagerActivity
package com.xiaobin.security.ui;import java.util.ArrayList;
import java.util.List;import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import com.xiaobin.security.R;
import com.xiaobin.security.domain.TaskInfo;
import com.xiaobin.security.engine.TaskInfoProvider;
import com.xiaobin.security.utils.TextFormater;public class ProcessManagerActivity extends Activity implements OnClickListener
{private static final int LOAD_FINISH = 1;private TextView tv_process_count;private TextView tv_process_memory;private LinearLayout ll_process_load;private ListView lv_process_list;private Button bt_process_clear;private Button bt_process_setting;private CheckBox cb_process_state;private ActivityManager activityManager;private List<RunningAppProcessInfo> runningAppProcessInfos;private TaskInfoProvider taskInfoProvider;private List<TaskInfo> taskInfos;private TaskInfoAdapter adapter;private List<TaskInfo> userTaskInfos;private List<TaskInfo> systemTaskInfos;@SuppressLint("HandlerLeak")private Handler handler = new Handler(){public void handleMessage(Message msg){switch (msg.what){case LOAD_FINISH:ll_process_load.setVisibility(View.INVISIBLE);adapter = new TaskInfoAdapter();lv_process_list.setAdapter(adapter);break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);// 请求一个自己定义的title,但有一些Android系统是被修改过的,// 所以有可能是无法请求的,如乐Phone或小米的手机,这些系统是被修改过的,// 所以就要判断一下是否请求成功boolean flags = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);setContentView(R.layout.process_manager);if (flags){// 设置自定义的titlegetWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.process_manager_title);}tv_process_count = (TextView) findViewById(R.id.tv_process_count);tv_process_memory = (TextView) findViewById(R.id.tv_process_memory);ll_process_load = (LinearLayout) findViewById(R.id.ll_process_load);lv_process_list = (ListView) findViewById(R.id.lv_process_list);bt_process_clear = (Button) findViewById(R.id.bt_process_clear);bt_process_setting = (Button) findViewById(R.id.bt_process_setting);bt_process_clear.setOnClickListener(this);bt_process_setting.setOnClickListener(this);initData();lv_process_list.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id){// adapter里面的getItem返回的值Object obj = lv_process_list.getItemAtPosition(position);if (obj instanceof TaskInfo){cb_process_state = (CheckBox) view.findViewById(R.id.cb_process_manager_state);TaskInfo taskInfo = (TaskInfo) obj;if (taskInfo.isCheck()){taskInfo.setCheck(false);cb_process_state.setChecked(false);}else{taskInfo.setCheck(true);cb_process_state.setChecked(true);}}}});}@Overridepublic void onClick(View v){switch (v.getId()){case R.id.bt_process_clear:killTask();break;case R.id.bt_process_setting:break;default:break;}}private void initData(){// 因为这个title是要显示当前进程数目和可用内存的,所以我们每次在这里都调用一下,以更新数据initTitle();ll_process_load.setVisibility(View.VISIBLE);new Thread(new Runnable(){@Overridepublic void run(){taskInfoProvider = new TaskInfoProvider(ProcessManagerActivity.this);taskInfos = taskInfoProvider.getAllTask(runningAppProcessInfos);Message msg = new Message();msg.what = LOAD_FINISH;handler.sendMessage(msg);}}).start();}// 拿到当前运行的进程数目private int getRunningAppCount(){runningAppProcessInfos = activityManager.getRunningAppProcesses();return runningAppProcessInfos.size();}// 拿到系统剩余的内存private String getAvailMemory(){// new一个内存的对象MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();// 拿到现在系统里面的内存信息activityManager.getMemoryInfo(memoryInfo);// 拿到有效的内存空间long size = memoryInfo.availMem;return TextFormater.dataSizeFormat(size);}// 设置title的信息private void initTitle(){tv_process_count.setText("进程数目:" + getRunningAppCount());tv_process_memory.setText("剩余内存:" + getAvailMemory());}// 一键清理的函数private void killTask(){int total = 0;int memorySize = 0;for (TaskInfo taskInfo : systemTaskInfos){if (taskInfo.isCheck()){// 杀死进程activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}for (TaskInfo taskInfo : userTaskInfos){if (taskInfo.isCheck()){activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}Toast.makeText(this,"已经杀死了" + total + "个进程!释放了"+ TextFormater.getSizeFromKB(memorySize) + "空间",Toast.LENGTH_SHORT).show();// 重新加载界面adapter = new TaskInfoAdapter();lv_process_list.setAdapter(adapter);}// ===========================================================================private class TaskInfoAdapter extends BaseAdapter{public TaskInfoAdapter(){// 存放用户的应用进程userTaskInfos = new ArrayList<TaskInfo>();// 存放系统的应用进程systemTaskInfos = new ArrayList<TaskInfo>();for (TaskInfo taskInfo : taskInfos){if (taskInfo.isSystemProcess()){systemTaskInfos.add(taskInfo);}else{userTaskInfos.add(taskInfo);}}}@Overridepublic int getCount(){// 加上两个标签,一个是系统标签,一个是用户标签return taskInfos.size() + 2;}@Overridepublic Object getItem(int position){if (position == 0){return 0; // 显示成用户应用的标签}else if (position <= userTaskInfos.size()){return userTaskInfos.get(position - 1); // 用户应用进程的条目}else if (position == userTaskInfos.size() + 1){return position; // 显示成系统进程的标签}else if (position <= taskInfos.size() + 2){// 系统应用进程的条目return systemTaskInfos.get(position - userTaskInfos.size() - 2);}else{return position;}}@Overridepublic long getItemId(int position){return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent){View view;TaskInfoViews views;TaskInfo taskInfo;if (position == 0){// 显示成用户应用的标签return newTextView("用户进程(" + userTaskInfos.size() + ")");}else if (position <= userTaskInfos.size()){// 用户应用进程的条目taskInfo = userTaskInfos.get(position - 1);}else if (position == userTaskInfos.size() + 1){// 显示成系统进程的标签return newTextView("系统进程(" + systemTaskInfos.size() + ")");}else if (position <= taskInfos.size() + 2){// 系统应用进程的条目taskInfo = systemTaskInfos.get(position - userTaskInfos.size()- 2);}else{taskInfo = new TaskInfo();}if (convertView == null || convertView instanceof TextView){view = View.inflate(ProcessManagerActivity.this,R.layout.process_manager_item, null);views = new TaskInfoViews();views.iv_process_icon = (ImageView) view.findViewById(R.id.iv_process_manager_icon);views.tv_process_name = (TextView) view.findViewById(R.id.tv_process_manager_name);views.tv_process_memory = (TextView) view.findViewById(R.id.tv_process_manager_memory);views.cb_process_state = (CheckBox) view.findViewById(R.id.cb_process_manager_state);view.setTag(views);}else{view = convertView;views = (TaskInfoViews) view.getTag();}views.iv_process_icon.setImageDrawable(taskInfo.getIcon());views.tv_process_name.setText(taskInfo.getName());views.tv_process_memory.setText("占用内存:"+ TextFormater.getSizeFromKB(taskInfo.getMemory()));views.cb_process_state.setChecked(taskInfo.isCheck());return view;}private TextView newTextView(String title){TextView tv_title = new TextView(ProcessManagerActivity.this);tv_title.setText(title);return tv_title;}}private class TaskInfoViews{ImageView iv_process_icon;TextView tv_process_name;TextView tv_process_memory;CheckBox cb_process_state;}}
好啦,今天就到这里,有什么不明白的,可以指出来
最后,和大家说一下
为了方便大家的交流,我创建了一个群,这样子大家有什么疑问也可以在群上交流
群号是298440981
今天源码下载
这篇关于Android项目实战--手机卫士29--杀死后台进程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!