系统进程管理

时间:2022-10-02 20:32:32

  最近写了个手机管理软件,涉及到了手机进程管理方面的内容,在此总结一下,记录实现过程以备后用,首先,实现的功能如下:
  1. 手机可以显示当前系统的内存
  2. 显示当前系统占用的内存和剩余内存
  3. 列出应用软件的进程,包括,软件名字,软件图标
  4. 列出系统的进程,包,名字,图标
  
  话不多说,先来实现前两个功能,为了完成1和2两步这里先使用一个简单布局布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.processdemo.activity.MainActivity">


<RelativeLayout
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">


<TextView
android:id="@+id/tv_process_count"
android:text="进程总数: xx"
android:textSize="18sp"
android:textColor="#000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>


<TextView
android:id="@+id/tv_process_space"
android:text="剩余/总共: x / x"
android:textSize="18sp"
android:textColor="#000"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>


</RelativeLayout>

</LinearLayout>

  布局很简单,就是在顶部放置两个TextView用于显示进程总数、内存大小和已使用内存。
  然后,封装一个引擎类,用来获取这些数据,代码如下:

package com.processdemo.engine;

import android.app.ActivityManager;
import android.content.Context;

import java.util.List;

/**
* Created by BadFlag on 2017/6/20.<br />
* 获取进程信息的方法
*/

public class ProcessEngine {
private static ProcessEngine processEngine;
private ProcessEngine() {}
public static ProcessEngine getInstance(Context context) {
if (processEngine == null) {
processEngine = new ProcessEngine();
}
return processEngine;
}

/**
* 获取当前运行的进程总数
* @param context 上下文对象
* @return
*/

public int getProcessCount(Context context) {
// 1 得到ActivityManager
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 2 获取正在运行进程的集合
List<ActivityManager.RunningAppProcessInfo> appProcessInfos = activityManager.getRunningAppProcesses();
// 3 返回集合总数
return appProcessInfos.size();
}

/**
* 获得可以用内存大小
* @param context 上下文对象
* @return 内存大小单位是byte
*/

public long getAvailSpace(Context context) {
// 1 得到ActivityManager
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 2 获得内存可用对象
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// 3 给memoryInfo对象赋值
activityManager.getMemoryInfo(memoryInfo);
// 4 返回可用空间
return memoryInfo.availMem;
}

/**
* 获得内存总大小,<font color='red' >注意,只能用在API级别在16以上的版本</font>
* @param context 上下文对象
* @return 内存大小单位是byte
*/

public long getTotalSpace(Context context) {
// 1 得到ActivityManager
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 2 获得内存可用对象
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// 3 给memoryInfo对象赋值
activityManager.getMemoryInfo(memoryInfo);
// 4 返回内存总大小
return memoryInfo.totalMem;
}
}

  接下来是在MainActivity中使用这个类即可,代码如下:

package com.processdemo.activity;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import com.processdemo.R;
import com.processdemo.engine.ProcessEngine;

import org.xutils.view.annotation.ViewInject;
import org.xutils.x;

public class MainActivity extends AppCompatActivity {

@ViewInject(R.id.tv_process_count)
private TextView mProcessCount;

@ViewInject(R.id.tv_process_space)
private TextView mProcessSpace;

private ProcessEngine mProcessEngine;

// 进程总数
private int mCount;
// 可利用内存
private long mAvailSpace;
// 内存总大小
private long mTotalSpace;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
x.view().inject(this);
mProcessEngine = ProcessEngine.getInstance(x.app());
initData();
}

private void initData() {
// 获取进程总数
mCount = mProcessEngine.getProcessCount(x.app());
mProcessCount.setText("进程总数: " + mCount);
// 获取可用内存
mAvailSpace = mProcessEngine.getAvailSpace(x.app());
// 格式化,将获取的byte大小的值变成KB,MB或GB等单位
String availSpaceStr = android.text.format.Formatter.formatFileSize(x.app(), mAvailSpace);
// 获取内存总大小
mTotalSpace = mProcessEngine.getTotalSpace(x.app());
String totalSpaceStr = android.text.format.Formatter.formatFileSize(x.app(), mTotalSpace);
mProcessSpace.setText("剩余/总共: " + availSpaceStr + " / " + totalSpaceStr + " ");
Toast.makeText(x.app(), "读取进程数据完毕!", Toast.LENGTH_SHORT).show();
}
}

  这里的x.app()是获得Application的Context对象,是xUtils3的写法,关于这个开源框架以后有时间在总结一下,至此,前两个功能就完成了,效果如下:
                系统进程管理
  然后再来实现功能3和功能4,首先,要获取全部进程的信息,一般这种显示都是采用ListView的方式,使用ListView时就要有个List集合,而这个集合里就是封装了一个JavaBean对象,这个对象就是每一个进程的信息,所以,要先写一个进程的实例类,代码如下:

package com.processdemo.model;

import android.graphics.drawable.Drawable;

/**
* Created by BadFlag on 2017/6/20.<br />
* 进程信息的实例类
*/

public class ProcessModel {

// 程序名称
private String name;

// 程序包名
private String packageName;

// 程序图标
private Drawable icon;

// 应用占用的内存
private long memSize;

// 是否被选中
private boolean isCheck;

// 是否为系统应用
private boolean isSystem;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPackageName() {
return packageName;
}

public void setPackageName(String packageName) {
this.packageName = packageName;
}

public Drawable getIcon() {
return icon;
}

public void setIcon(Drawable icon) {
this.icon = icon;
}

public long getMemSize() {
return memSize;
}

public void setMemSize(long memSize) {
this.memSize = memSize;
}

public boolean isCheck() {
return isCheck;
}

public void setCheck(boolean check) {
isCheck = check;
}

public boolean isSystem() {
return isSystem;
}

public void setSystem(boolean system) {
isSystem = system;
}
}

  完成这些后就可以继续扩展ProcessEngine类的功能了,在ProcessEngine类中添加新的函数,代码如下:

/**
* 获得手机系统的所有进程信息
* @param context 上下文环境
* @return 进程模型集合
*/

public List<ProcessModel> getProcessInfo(Context context) {
// 1 创建用于返回的进程信息模型集合
List<ProcessModel> processModels = new ArrayList<>();
// 2 得到ActivityManager
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 3 获取正在运行进程的集合
List<ActivityManager.RunningAppProcessInfo> runInfo = activityManager.getRunningAppProcesses();
// 4 获取管理者对象
PackageManager packageManager = context.getPackageManager();
// 5 循环遍历进程信息,并进行封装
for (ActivityManager.RunningAppProcessInfo info : runInfo) {
ProcessModel pModel = new ProcessModel();
// 获取包名
pModel.setPackageName(info.processName);
// 获取进程占用的内存大小,传递进程号对应的数组,返回多个进程信息
Debug.MemoryInfo[] processMemoryInfo = activityManager.getProcessMemoryInfo(new int[]{info.pid});
Debug.MemoryInfo memoryInfo = processMemoryInfo[0];
// 获取已使用大小
pModel.setMemSize(memoryInfo.getTotalPrivateDirty() * 1024);
try {
// 获取应用名称
ApplicationInfo appInfo = packageManager.getApplicationInfo(pModel.getPackageName(), 0);
pModel.setName(appInfo.loadLabel(packageManager).toString());
// 获取应用的图标
pModel.setIcon(appInfo.loadIcon(packageManager));
// 判断是否为系统进程
if (ApplicationInfo.FLAG_SYSTEM == (appInfo.flags & ApplicationInfo.FLAG_SYSTEM )) {
pModel.setSystem(true);
} else {
pModel.setSystem(false);
}
} catch (PackageManager.NameNotFoundException e) {
// 如果没有包名用程序名字设定
pModel.setName(info.processName);
// 没有图标就用默认图标设定
pModel.setIcon(ContextCompat.getDrawable(x.app(), R.mipmap.ic_launcher));
// 默认为系统进程
pModel.setSystem(true);
// e.printStackTrace();
}
processModels.add(pModel);
}
return processModels;
}

  布局界面增加一个ListView用来显示,进程信息代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.processdemo.activity.MainActivity">


<RelativeLayout
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">


<TextView
android:id="@+id/tv_process_count"
android:text="进程总数: xx"
android:textSize="18sp"
android:textColor="#000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>


<TextView
android:id="@+id/tv_process_space"
android:text="剩余/总共: x / x"
android:textSize="18sp"
android:textColor="#000"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>


</RelativeLayout>

<ListView
android:id="@+id/lv_show_process"
android:layout_width="match_parent"
android:layout_height="match_parent" />


</LinearLayout>

  接下来看MainActivity中如何使用这个函数,代码如下:

@Override
protected void onStart() {
super.onStart();
getProcessData();
}

private void getProcessData() {
new Thread(new Runnable() {
@Override
public void run() {
mProcessModels = mProcessEngine.getProcessInfo(getApplicationContext());
mHandler.sendEmptyMessage(0);
}
}).start();
}

  由于获取进程信息的代码是耗时的所以将其放入到线程中运行,放入到onStrat()方法中是因为我觉得如果再别的界面杀死了一些进程,但恢复到这个界面后应该是重新刷新的,但是想法对不对我也不知道。
  在程序的最后,由于是在线程中,所以调用了Handler来通知外边已经将所有的进程信息获取完毕了,可以开始显示了。Handler的代码如下:

private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 收到通知就说明获取到了全部进程信息,可以设置适配器了
mProcessShow.setAdapter(new ProcessAdapter());
}
};

  没有很多消息种类就是简单做个接收处理,主要是看ProcessAdapter的开发,代码如下:

class ProcessAdapter extends BaseAdapter {

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

@Override
public ProcessModel getItem(int position) {
return mProcessModels.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(getApplicationContext(), R.layout.process_show_item, null);
}
// 设置图标
Drawable appIcon = mProcessModels.get(position).getIcon();
ImageView appImage = (ImageView) convertView.findViewById(R.id.iv_process_icon);
appImage.setBackground(appIcon);
// 设置进程名称和包名
TextView appName = (TextView) convertView.findViewById(R.id.tv_process_name);
String formatString = String.format("%s (%s)",
mProcessModels.get(position).getName(),
mProcessModels.get(position).getPackageName());
appName.setText(formatString);
// 设置进程级别
TextView appLeve = (TextView) convertView.findViewById(R.id.tv_process_level);
if (mProcessModels.get(position).isSystem()) {
appLeve.setText("系统进程");
} else {
appLeve.setText("用户进程");
}
// 设置占用大小
String availSpaceStr = android.text.format.Formatter.formatFileSize(x.app(),
mProcessModels.get(position).getMemSize());
TextView appSpace = (TextView) convertView.findViewById(R.id.tv_process_mem);
appSpace.setText("占用内存:" + availSpaceStr);
return convertView;
}
}

  条目的布局如下:

<?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="match_parent"
android:padding="5dp"
android:orientation="vertical">


<ImageView
android:id="@+id/iv_process_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@mipmap/ic_launcher"/>


<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv_process_icon"
android:layout_marginLeft="5dp"
android:orientation="vertical">


<TextView
android:id="@+id/tv_process_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="进程名称"
android:textColor="#000"/>


<TextView
android:id="@+id/tv_process_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="进程级别"
android:textColor="#000"/>


<TextView
android:id="@+id/tv_process_mem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="占用内存:"
android:textColor="#000"/>


</LinearLayout>

</RelativeLayout>

  至此,3和4也都完成了,效果如下:
                系统进程管理

  接下来还会用关闭进程的操作,等写完这部分代码后在继续总结。
  代码地址:GitHub地址