Android之——获取进程总和、内存、任务列表

Android之——获取进程总数、内存、任务列表
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47263863

如今,基于Android平台的应用越来越多,不乏这样一些应用程序,这些应用可以对手机中的进程,内存和任务列表进行管理。Android系统中没有自带的应用程序对这些数据进行管理。大家不禁会说,Android的应用设置里面有这些功能啊!是的,虽然应用设置里面有,但是我们如果想看一下系统的进程,还要跑到系统设置里面去看吗?这样是不是很麻烦?是不是很挫呢?那获取Android系统的进程总数、内存、任务列表是怎样实现的呢?亲们,别着急,下面我们就一起来实现这些功能吧!注意看哦,不要偷懒!

一、原理

首先,我们还是要来说说这些所谓的原理级别的东东吧,不然说了半天,大家可能也是一知半解的。

任务尽可能长时间的保存一个应用。内存出现不足的时候,就会去由操作系统杀死进程:
进程的重要级别:
1 Foreground process 前台进程
  1.1 activity  onResume()
  1.2 一个前台进程的activity绑定了另外一个进程的service
  1.3 service里面调用startForeground
  1.4 service onCreate()  onStart()  onDestory()
  1.5 BroadcastReceiver  onReceive()
2 Visible process 可视进程
  2.1  activity  onPause()
  2.2  一个可视的activity绑定了另一进程的服务
3 Service process 服务进程  
  后台的服务   播放器  下载  复制文件 
4 Background process 后台进程
  任务栈里面还有activity实例的引用,但是该应用在后台
5 Empty process 空进程
1 如果是去获取系统里面安装的信息,这个信息不是动态变化的  PackageManager 

2 如果该信息是变化的   ActivityManager  任务管理器

在这个示例中,我们会通过List将获取到的任务进程列表显示到UI上。

好了,原理啰嗦完了,这里的原理我不同于以往的写法,而是将重要的知识点列出来了,亲们,是不是很简单?看完原理,咱们一起实现这些功能吧。

二、实现

1、数据格式化类TextFormat

考虑到我们获取内存大小,和每个任务进程占用的内存大小时,会出现数据单位不统一的情况,这时,我们自己定义一个数据格式化类,来帮助我们实现数据单位的格式化。

具体代码如下:

package cn.lyz.mobilesafe.utils;

import java.text.DecimalFormat;

/**
 * 文本格式化工具类
 * @author liuyazhuang
 *
 */
public class TextFormat {
	
	/**
	 * 格式化数据
	 * @param data
	 * @return
	 */
	public static String formatByte(long data){
		DecimalFormat format = new DecimalFormat("##.##");
		if(data < 1024){
			return data+"bytes";
		}else if(data < 1024 * 1024){
			return format.format(data/1024f) +"KB";
		}else if(data < 1024 * 1024 * 1024){
			return format.format(data/1024f/1024f) +"MB";
		}else if(data < 1024 * 1024 * 1024 * 1024){
			return format.format(data/1024f/1024f/1024f) +"GB";
		}else{
			return "超出统计范围";
		}
	}
}

2、任务信息实体类TaskInfo

在我们这个任务列表中会显示的内容有图标、名称、每个应用占用的内存、包名、进程id等信息,为了使程序更加面向对象化,也更加体现面向对象的封装性,我将这些信息封装为一个java实体类。

具体实现代码如下:

package cn.lyz.mobilesafe.domain;

import android.graphics.drawable.Drawable;

/**
 * 任务信息
 * @author liuyazhuang
 *
 */
public class TaskInfo {
	//图标
	private Drawable task_icon;
	//名称
	private String task_name;
	//占用的内存
	private long task_memory;
	//包名
	private String packageName;
	//进程id
	private int pid;
	
	public TaskInfo() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	public TaskInfo(Drawable task_icon, String task_name, long task_memory,
			String packageName, int pid) {
		super();
		this.task_icon = task_icon;
		this.task_name = task_name;
		this.task_memory = task_memory;
		this.packageName = packageName;
		this.pid = pid;
	}

	public Drawable getTask_icon() {
		return task_icon;
	}
	public void setTask_icon(Drawable task_icon) {
		this.task_icon = task_icon;
	}
	public String getTask_name() {
		return task_name;
	}
	public void setTask_name(String task_name) {
		this.task_name = task_name;
	}
	public long getTask_memory() {
		return task_memory;
	}
	public void setTask_memory(long task_memory) {
		this.task_memory = task_memory;
	}
	public String getPackageName() {
		return packageName;
	}
	public void setPackageName(String packageName) {
		this.packageName = packageName;
	}
	public int getPid() {
		return pid;
	}
	public void setPid(int pid) {
		this.pid = pid;
	}

	@Override
	public String toString() {
		return "TaskInfo [task_icon=" + task_icon + ", task_name=" + task_name
				+ ", task_memory=" + task_memory + ", packageName="
				+ packageName + ", pid=" + pid + "]";
	}
	
}

3、获取进程与内存信息的工具类TaskUtils

我把获取进程与内存信息的方法全部封装在了TaskUtils类中。

具体实现代码如下:

package cn.lyz.mobilesafe.utils;

import java.util.ArrayList;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import cn.lyz.mobilesafe.R;
import cn.lyz.mobilesafe.domain.TaskInfo;

/**
 * 任务相关工具类
 * @author liuyazhuang
 *
 */
public class TaskUtils {
	
	/**
	 * 获取当前正在进行的进程数
	 * @param context
	 * @return
	 */
	public static int getRunningAppProcessInfoSize(Context context){
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		return am.getRunningAppProcesses().size();
	}
	
	/**
	 * 获取系统可用内存
	 * @param context
	 * @return
	 */
	public static long getAvailMem(Context context){
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		//得到可用内存
		MemoryInfo outInfo = new MemoryInfo();
		am.getMemoryInfo(outInfo);
		long availMem = outInfo.availMem; //单位是byte
		return availMem;
	}
	
	/**
	 * 获取系统所有的进程信息列表
	 * @param context
	 * @return
	 */
	public static List<TaskInfo> getTaskInfos(Context context){
		List<TaskInfo> taskInfos  = new ArrayList<TaskInfo>();
		PackageManager pm = context.getPackageManager();
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();
		for(RunningAppProcessInfo info : runningAppProcesses){
			TaskInfo taskInfo = new TaskInfo();
			//进程名称
			String packageName = info.processName;
			taskInfo.setPackageName(packageName);
			try {
				ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0);
				//图标
				Drawable task_icon = applicationInfo.loadIcon(pm);
				if(task_icon == null){
					taskInfo.setTask_icon(context.getResources().getDrawable(R.drawable.ic_launcher));
				}else{
					taskInfo.setTask_icon(task_icon);
				}
				//名称
				String task_name = applicationInfo.loadLabel(pm).toString();
				taskInfo.setTask_name(task_name);
			} catch (NameNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			//进程id
			int pid = info.pid;
			taskInfo.setPid(pid);
			//获取进程占用的内存
			android.os.Debug.MemoryInfo[] processMemoryInfo = am.getProcessMemoryInfo(new int[]{pid});
			android.os.Debug.MemoryInfo memoryInfo  = processMemoryInfo[0];
			long totalPrivateDirty = memoryInfo.getTotalPrivateDirty(); //KB
			taskInfo.setTask_memory(totalPrivateDirty);
			taskInfos.add(taskInfo);
		}
		return taskInfos;
	}
}

4、程序显示界面TaskManagerActivity

这个类中的内容比较多,我们分解来看吧。

1)属性字段

以下代码是我们这个类中,所有的属性字段

	protected static final int SUCCESS_GETTASKINFO = 0;
	private TextView tv_task_manager_task_count;
	private TextView tv_task_manager_task_memory;
	private ListView lv_taskmanage;
	private RelativeLayout rl_loading;
	private ProgressBar pb;
	private List<TaskInfo> taskInfos;
	private TaskManagerAdapter mAdapter;

2)自定义适配器类TaskManagerAdapter

我在TaskManagerActivity类中,自定义了ListView的适配器。这里我用到了ListView的优化策略,使用了ViewHolder来优化ListView。有关ListView优化的策略,大家可以参考《Android之——ListView优化》一文。

具体代码如下:

	/**
	 * 自定义适配器
	 * @author liuyazhuang
	 *
	 */
	private class TaskManagerAdapter extends BaseAdapter{
		private LayoutInflater mInflater;
		public TaskManagerAdapter(){
			mInflater = getLayoutInflater();
		}
		@Override
		public int getCount() {
			return taskInfos.size();
		}

		@Override
		public Object getItem(int position) {
			return taskInfos.get(position);
		}

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

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view = null;
			ViewHolder holder = null;
			if(convertView != null){
				view = convertView;
				holder = (ViewHolder) view.getTag();
			}else{
				view = mInflater.inflate(R.layout.task_manager_item, null);
				holder = new ViewHolder();
				holder.iv_task_manager_icon = (ImageView) view.findViewById(R.id.iv_task_manager_icon);
				holder.iv_task_manager_name = (TextView) view.findViewById(R.id.tv_task_manager_name);
				holder.iv_task_manager_memory = (TextView) view.findViewById(R.id.tv_task_manager_memory);
				
				view.setTag(holder);
			}
			TaskInfo taskInfo = taskInfos.get(position);
			holder.iv_task_manager_icon.setImageDrawable(taskInfo.getTask_icon());
			holder.iv_task_manager_memory.setText("占用的内存:"+TextFormat.formatByte(taskInfo.getTask_memory()*1024));
			holder.iv_task_manager_name.setText(taskInfo.getTask_name());
			return view;
		}
	}
	
	static class ViewHolder{
		ImageView iv_task_manager_icon;
		TextView iv_task_manager_name;
		TextView iv_task_manager_memory;
	}

3)onCreate方法

这个方法主要实现的是,UI控件的初始化,由于或许进程列表是一个耗时的操作,所以我将它放在一个线程中,获取到进程信息后通过Handler将信息传递到UI线程显示数据。

具体实现代码如下:

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.task_manager);
		tv_task_manager_task_count  = (TextView) findViewById(R.id.tv_task_manager_task_count);
		tv_task_manager_task_memory = (TextView) findViewById(R.id.tv_task_manager_task_memory);
		lv_taskmanage = (ListView) findViewById(R.id.lv_taskmanage);
		rl_loading = (RelativeLayout) findViewById(R.id.rl_loading);
		pb = (ProgressBar) findViewById(R.id.pb);
		//获取ActivityManager系统服务
		int size = TaskUtils.getRunningAppProcessInfoSize(this);
		tv_task_manager_task_count.setText("进程数:"+size);
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				taskInfos = TaskUtils.getTaskInfos(getApplicationContext());
				Message msg = new Message();
				msg.what = SUCCESS_GETTASKINFO;
				mHandler.sendMessage(msg);
			}
		}).start();
	}

4)Handler

用于接收子线程传递过来的数据。

具体代码实现如下:

	private Handler mHandler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case SUCCESS_GETTASKINFO:
				long total = TaskUtils.getAvailMem(TaskManagerActivity.this);
				for(TaskInfo info : taskInfos){
					total += info.getTask_memory() * 1024;
				}
				//可用内存
				String availMemStr = TextFormat.formatByte(TaskUtils.getAvailMem(TaskManagerActivity.this));
				//总内存
				String totalMemStr = TextFormat.formatByte(total);
				tv_task_manager_task_memory.setText("可用/总内存:"+availMemStr+"/"+totalMemStr);
				
				mAdapter = new TaskManagerAdapter();
				rl_loading.setVisibility(View.GONE);
				lv_taskmanage.setAdapter(mAdapter);
				break;

			default:
				break;
			}
		};
	};

5)整体代码如下

package cn.lyz.mobilesafe.activity;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import cn.lyz.mobilesafe.R;
import cn.lyz.mobilesafe.domain.TaskInfo;
import cn.lyz.mobilesafe.utils.TaskUtils;
import cn.lyz.mobilesafe.utils.TextFormat;

/**
 * 任务管理
 * @author liuyazhuang
 *
 */
public class TaskManagerActivity extends Activity {
	protected static final int SUCCESS_GETTASKINFO = 0;
	private TextView tv_task_manager_task_count;
	private TextView tv_task_manager_task_memory;
	private ListView lv_taskmanage;
	private RelativeLayout rl_loading;
	private ProgressBar pb;
	private List<TaskInfo> taskInfos;
	private TaskManagerAdapter mAdapter;
	private Handler mHandler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case SUCCESS_GETTASKINFO:
				long total = TaskUtils.getAvailMem(TaskManagerActivity.this);
				for(TaskInfo info : taskInfos){
					total += info.getTask_memory() * 1024;
				}
				//可用内存
				String availMemStr = TextFormat.formatByte(TaskUtils.getAvailMem(TaskManagerActivity.this));
				//总内存
				String totalMemStr = TextFormat.formatByte(total);
				tv_task_manager_task_memory.setText("可用/总内存:"+availMemStr+"/"+totalMemStr);
				
				mAdapter = new TaskManagerAdapter();
				rl_loading.setVisibility(View.GONE);
				lv_taskmanage.setAdapter(mAdapter);
				break;

			default:
				break;
			}
		};
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.task_manager);
		tv_task_manager_task_count  = (TextView) findViewById(R.id.tv_task_manager_task_count);
		tv_task_manager_task_memory = (TextView) findViewById(R.id.tv_task_manager_task_memory);
		lv_taskmanage = (ListView) findViewById(R.id.lv_taskmanage);
		rl_loading = (RelativeLayout) findViewById(R.id.rl_loading);
		pb = (ProgressBar) findViewById(R.id.pb);
		//获取ActivityManager系统服务
		int size = TaskUtils.getRunningAppProcessInfoSize(this);
		tv_task_manager_task_count.setText("进程数:"+size);
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				taskInfos = TaskUtils.getTaskInfos(getApplicationContext());
				Message msg = new Message();
				msg.what = SUCCESS_GETTASKINFO;
				mHandler.sendMessage(msg);
			}
		}).start();
	}
	
	/**
	 * 自定义适配器
	 * @author liuyazhuang
	 *
	 */
	private class TaskManagerAdapter extends BaseAdapter{
		private LayoutInflater mInflater;
		public TaskManagerAdapter(){
			mInflater = getLayoutInflater();
		}
		@Override
		public int getCount() {
			return taskInfos.size();
		}

		@Override
		public Object getItem(int position) {
			return taskInfos.get(position);
		}

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

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view = null;
			ViewHolder holder = null;
			if(convertView != null){
				view = convertView;
				holder = (ViewHolder) view.getTag();
			}else{
				view = mInflater.inflate(R.layout.task_manager_item, null);
				holder = new ViewHolder();
				holder.iv_task_manager_icon = (ImageView) view.findViewById(R.id.iv_task_manager_icon);
				holder.iv_task_manager_name = (TextView) view.findViewById(R.id.tv_task_manager_name);
				holder.iv_task_manager_memory = (TextView) view.findViewById(R.id.tv_task_manager_memory);
				
				view.setTag(holder);
			}
			TaskInfo taskInfo = taskInfos.get(position);
			holder.iv_task_manager_icon.setImageDrawable(taskInfo.getTask_icon());
			holder.iv_task_manager_memory.setText("占用的内存:"+TextFormat.formatByte(taskInfo.getTask_memory()*1024));
			holder.iv_task_manager_name.setText(taskInfo.getTask_name());
			return view;
		}
	}
	
	static class ViewHolder{
		ImageView iv_task_manager_icon;
		TextView iv_task_manager_name;
		TextView iv_task_manager_memory;
	}
}

5、页面布局

具体代码如下:

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

    <TextView
        style="@style/text_title_style"
        android:text="任 务 管 理" />

    <View style="@style/view_divide_line_style" />
	
    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dip">
        
        <TextView 
            android:id="@+id/tv_task_manager_task_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="进程数:20"/>
        
        <TextView 
            android:id="@+id/tv_task_manager_task_memory"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="可用/总内存:50MB/700MB"/>
    </RelativeLayout>

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <!--
       android:cacheColorHint="#00000000" 缓存的颜色  默认是黄色
       android:divider="#00ffffff" 分割线
       android:dividerHeight="3.0dip" 分割线的宽度
        -->
        <ListView
            android:id="@+id/lv_taskmanage"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:cacheColorHint="#00000000"
            android:divider="#fff"
            android:fastScrollEnabled="true"
            android:dividerHeight="1.0dip"
            android:paddingLeft="3.0dip"
            android:paddingRight="3.0dip" />

        <RelativeLayout
            android:id="@+id/rl_loading"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical" 
                android:layout_centerInParent="true">

                <ProgressBar
                    android:id="@+id/pb"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dip"
                    android:text="正在加载应用程序。。"
                    android:textColor="#fff"
                    android:textSize="22sp" />
            </LinearLayout>
        </RelativeLayout>
    </FrameLayout>
</LinearLayout>

6、ListView条目布局

具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:paddingBottom="8.0dip"
    android:paddingLeft="6.0dip"
    android:paddingRight="5.0dip"
    android:paddingTop="8.0dip" >

    <ImageView
        android:id="@+id/iv_task_manager_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/tv_task_manager_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="4.0dip"
        android:layout_toRightOf="@id/iv_task_manager_icon"
        android:textColor="#fff"
        android:text="我最摇摆"
        android:textSize="18.0dip" />
    
    <TextView
        android:id="@+id/tv_task_manager_memory"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/iv_task_manager_icon"
        android:layout_below="@id/tv_task_manager_name"
        android:textColor="#fff"
        android:text="占用内存:20KB"
        android:textSize="15sp" />

</RelativeLayout>

7、res/values下新建styles.xml文件

我们在这个文件中定义了一些样式,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="text_title_style">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:gravity">center</item>
        <item name="android:textColor">#42E700</item>
        <item name="android:textSize">25sp</item>
    </style>
    

    <style name="view_divide_line_style">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">1dip</item>
        <item name="android:layout_marginTop">5dip</item>
        <item name="android:background">@drawable/devide_line</item>
    </style>
    

    <style name="text_content_style">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textSize">20sp</item>
        <item name="android:textColor">#42E700</item>
        <item name="android:layout_marginTop">5dip</item>
    </style>

    <style name="image_start_online_style">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginRight">5dip</item>
        <item name="android:src">@android:drawable/presence_online</item>
    </style>
    
    <style name="image_start_offline_style" parent="image_start_online_style">
        <item name="android:src">@android:drawable/presence_invisible</item>
    </style>
    

    <style name="button_next_style">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_alignParentRight">true</item>
        <item name="android:layout_alignParentBottom">true</item>
        <item name="android:text">下一步</item>
        <item name="android:drawableRight">@drawable/next</item>
    </style>

    <style name="button_pre_style">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_alignParentLeft">true</item>
        <item name="android:layout_alignParentBottom">true</item>
        <item name="android:text">上一步</item>
        <item name="android:drawableLeft">@drawable/previous</item>
    </style>
 
</resources>

8、授权

最后别忘了,在 AndroidManifest.xml进行权限注册。

具体如下:

 <uses-permission android:name="android.permission.GET_TASKS"/>

三、运行效果

Android之——获取进程总和、内存、任务列表

Android之——获取进程总和、内存、任务列表

四、温馨提示

本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。

版权声明:本文为博主原创文章,未经博主允许不得转载。