今天呢,我们就继续我们的进程管理啦,昨天我们就讲到了拿到进程数目,以及可用的内存,那么今天,我们就把那些进程一个个的显示出来,
但在做今天这个之前,我先给大家提个醒,我觉得那个程序锁的界面有点不好看,所以就修改了一下,大家到时可以看看源码,我们就先把今天要做的,和那个程序锁的给大家看看先吧
大家可以看到,我们这个界面也是挺简单的,有一个标签把系统的进程和用户的进程给区分开来,所以我们到时在显示在listview的时候就要小心处理了,
首先,我们要先新建一个model类,用来存放那些进程的信息
com.xiaobin.security.domain.TaskInfo
package com.xiaobin.security.domain; import android.graphics.drawable.Drawable; public class TaskInfo { private String name; private Drawable icon; private int id; //以KB作为单位 private int memory; private boolean isCheck; private String packageName; //是否为系统进程 private boolean isSystemProcess; public String getName() { return name; } public void setName(String name) { this.name = name; } public Drawable getIcon() { return icon; } public void setIcon(Drawable icon) { this.icon = icon; } public int getId() { return id; } public void setId(int id) { this.id = id; } public boolean isCheck() { return isCheck; } public void setCheck(boolean isCheck) { this.isCheck = isCheck; } public String getPackageName() { return packageName; } public void setPackageName(String packageName) { this.packageName = packageName; } public int getMemory() { return memory; } public void setMemory(int memory) { this.memory = memory; } public boolean isSystemProcess() { return isSystemProcess; } public void setSystemProcess(boolean isSystemProcess) { this.isSystemProcess = isSystemProcess; } }
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.domain.TaskInfo; public class TaskInfoProvider { private PackageManager packageManager; private ActivityManager activityManager; public TaskInfoProvider(Context context) { 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)); // 可以返回一个内存信息的数组,传进去的id有多少个,就返回多少个对应id的内存信息 MemoryInfo[] memoryInfos = activityManager .getProcessMemoryInfo(new int[] { id }); // 拿到占用的内存空间 int memory = memoryInfos[0].getTotalPrivateDirty(); taskInfo.setMemory(memory); taskInfos.add(taskInfo); taskInfo = null; } catch (Exception e) { e.printStackTrace(); } } return taskInfos; } // 判断某一个应用程序是不是用户的应用程序,如果是返回true,否则返回false public 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; } }
那么,我们就可以读取到它们的processName字段啦,其实这个字段就是这个应用的包名啦,那么, 拿到了包名之后,我们就可以拿到很多信息的啦。
如上面写到的,通过PackageManager来拿到一个applicationInfo,拿到这个对象也好办啦,什么应用名字啦,图标啦,都可以拿到啦,这些我们之前在程序锁啊,应用管理这些都写过啦,上面也再写了一次,当复习啦。
接下来,我们就要读取这个进程占用的内存啦,其实这个操作也很简单啦,就是通过ActivityManager对象来调用它里面的方法getProcessMemoryInfo,通过传递
一个id的数组进去,就可以拿到,对应id数组里面的占用内存信息啦,所以还是挺简单的。
大家还会看到,我们上面有个方法,就是判断是不是系统应用的,其实这个方法,我们之前在应用管理那里也有写过的,但是我当时没怎么说,造成了不少人的误解,那我今天就和大家说一下吧
我们拿到的ApplicationInfo对象里面有个flags,就是标记我们应用的类别的,如FLAG_SYSTEM就是一个系统应用啦,FLAG_UPDATED_SYSTEM_APP就是一个可升级的系统应用啦,但如果用户把它升级了,那么,就应该把它当成是用户的应用的啦,所以我们上面就返回true啦
好啦,写完这个读取进程信息的类之后,我们就要回到我们的界面,显示出来的啦
因为我们读取这些信息都是很久的,所以我们就和程序锁啊,应用管理这些一样,用一个线程来加载这些东西,并显示一个进度条
private void initData() { //因为这个title是要显示当前进程数目和可用内存的,所以我们每次在这里都调用一下,以更新数据 initTitle(); ll_process_load.setVisibility(View.VISIBLE); new Thread(new Runnable() { @Override public void run() { taskInfoProvider = new TaskInfoProvider(ProcessManagerActivity.this); taskInfos = taskInfoProvider.getAllTask(runningAppProcessInfos); Message msg = new Message(); msg.what = LOAD_FINISH; handler.sendMessage(msg); } }).start(); }
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; } } };
因为我们要区分系统进程和用户进程嘛,还要加两个标签,所以那就处理起来有点麻烦的啦
首先,我们要区分系统进程,和用户进程,那么我们就用两个list来分别存放它们,在adapter的构造方法里面,对它们进行初始化
public TaskInfoAdapter() { //存放用户的应用进程 userTaskInfo = new ArrayList<TaskInfo>(); //存放系统的应用进程 systemTaskInfo = new ArrayList<TaskInfo>(); for(TaskInfo taskInfo : taskInfos) { if(taskInfo.isSystemProcess()) { systemTaskInfo.add(taskInfo); } else { userTaskInfo.add(taskInfo); } } }
@Override public int getCount() { //加上两个标签,一个是系统标签,一个是用户标签 return taskInfos.size() + 2; }
@Override public Object getItem(int position) { if(position == 0) { return 0; //显示成用户应用的标签 } else if(position <= userTaskInfo.size()) { return userTaskInfo.get(position - 1); //用户应用进程的条目 } else if(position == userTaskInfo.size() + 1) { return position; //显示成系统进程的标签 } else if(position <= taskInfos.size() + 2) { //系统应用进程的条目 return systemTaskInfo.get(position - userTaskInfo.size() - 2); } else { return position; } }
@Override public View getView(int position, View convertView, ViewGroup parent) { View view; TaskInfoViews views; TaskInfo taskInfo; if(position == 0) { //显示成用户应用的标签 return newTextView("用户进程(" + userTaskInfo.size() + ")"); } else if(position <= userTaskInfo.size()) { //用户应用进程的条目 taskInfo = userTaskInfo.get(position - 1); } else if(position == userTaskInfo.size() + 1) { //显示成系统进程的标签 return newTextView("系统进程(" + systemTaskInfo.size() + ")"); } else if(position <= taskInfos.size() + 2) { //系统应用进程的条目 taskInfo = systemTaskInfo.get(position - userTaskInfo.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; }
如果对上面代码有什么不明白的,可以说出来
好啦,写到这里,我们的逻辑就基本上完成的啦,下面把activity的完整类和布局文件粘出来
process_manager.item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="65dip" android:background="@drawable/item_background_selector"> <ImageView android:id="@+id/iv_process_manager_icon" android:layout_width="60dip" android:layout_height="60dip" android:layout_alignParentLeft="true" android:scaleType="fitXY" android:src="@drawable/app" android:contentDescription="@string/hello_world"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="65dip" android:layout_toRightOf="@id/iv_process_manager_icon" android:layout_marginLeft="10dip" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/tv_process_manager_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="#ff000000" android:text="@string/hello_world"/> <TextView android:id="@+id/tv_process_manager_memory" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="#ff000000" android:text="@string/hello_world"/> </LinearLayout> <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"/> </RelativeLayout>
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.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 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 ActivityManager activityManager; private List<RunningAppProcessInfo> runningAppProcessInfos; private TaskInfoProvider taskInfoProvider; private List<TaskInfo> taskInfos; private TaskInfoAdapter adapter; @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; } } }; @Override protected 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) { // 设置自定义的title getWindow().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(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_process_clear: 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() { @Override public 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 class TaskInfoAdapter extends BaseAdapter { private List<TaskInfo> userTaskInfo; private List<TaskInfo> systemTaskInfo; public TaskInfoAdapter() { // 存放用户的应用进程 userTaskInfo = new ArrayList<TaskInfo>(); // 存放系统的应用进程 systemTaskInfo = new ArrayList<TaskInfo>(); for (TaskInfo taskInfo : taskInfos) { if (taskInfo.isSystemProcess()) { systemTaskInfo.add(taskInfo); } else { userTaskInfo.add(taskInfo); } } } @Override public int getCount() { // 加上两个标签,一个是系统标签,一个是用户标签 return taskInfos.size() + 2; } @Override public Object getItem(int position) { if (position == 0) { return 0; // 显示成用户应用的标签 } else if (position <= userTaskInfo.size()) { return userTaskInfo.get(position - 1); // 用户应用进程的条目 } else if (position == userTaskInfo.size() + 1) { return position; // 显示成系统进程的标签 } else if (position <= taskInfos.size() + 2) { // 系统应用进程的条目 return systemTaskInfo.get(position - userTaskInfo.size() - 2); } else { return position; } } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; TaskInfoViews views; TaskInfo taskInfo; if (position == 0) { // 显示成用户应用的标签 return newTextView("用户进程(" + userTaskInfo.size() + ")"); } else if (position <= userTaskInfo.size()) { // 用户应用进程的条目 taskInfo = userTaskInfo.get(position - 1); } else if (position == userTaskInfo.size() + 1) { // 显示成系统进程的标签 return newTextView("系统进程(" + systemTaskInfo.size() + ")"); } else if (position <= taskInfos.size() + 2) { // 系统应用进程的条目 taskInfo = systemTaskInfo.get(position - userTaskInfo.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
今天源码下载