您的位置:首页 > 移动开发 > Android开发

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

2015-08-03 23:27 405 查看
转载请注明出处:/article/8380835.html

如今,基于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"/>


三、运行效果





四、温馨提示

本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: