編輯:關於Android編程
如今,基於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上。
好了,原理啰嗦完了,這裡的原理我不同於以往的寫法,而是將重要的知識點列出來了,親們,是不是很簡單?看完原理,咱們一起實現這些功能吧。
考慮到我們獲取內存大小,和每個任務進程占用的內存大小時,會出現數據單位不統一的情況,這時,我們自己定義一個數據格式化類,來幫助我們實現數據單位的格式化。
具體代碼如下:
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 超出統計范圍;
}
}
}
在我們這個任務列表中會顯示的內容有圖標、名稱、每個應用占用的內存、包名、進程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 + ];
}
}
我把獲取進程與內存信息的方法全部封裝在了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 getTaskInfos(Context context){
List taskInfos = new ArrayList();
PackageManager pm = context.getPackageManager();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List 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;
}
}
這個類中的內容比較多,我們分解來看吧。
以下代碼是我們這個類中,所有的屬性字段
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 ListtaskInfos; private TaskManagerAdapter mAdapter;
我在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;
}
這個方法主要實現的是,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();
}
用於接收子線程傳遞過來的數據。
具體代碼實現如下:
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;
}
};
};
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 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;
}
}
具體代碼如下:
<framelayout android:layout_height="fill_parent" android:layout_width="fill_parent"> </framelayout>
具體代碼如下:
我們在這個文件中定義了一些樣式,具體代碼如下:
最後別忘了,在 AndroidManifest.xml進行權限注冊。
具體如下:


本實例中,為了方面,我把一些文字直接寫在了布局文件中和相關的類中,大家在真實的項目中要把這些文字寫在string.xml文件中,在外部引用這些資源,切記,這是作為一個Android程序員最基本的開發常識和規范,我在這裡只是為了方便直接寫在了類和布局文件中。
Android客戶端性能參數監控
背景: 在做android客戶端測試的時候,有時候需要監控cpu/mem/電量消耗/界面加載時間/流量等等指標。於是俺們就上下求索,網友告訴我
Android開發之在Eclipse中單元測試,在Class中進行單元測試與Activity中單元測試
我們在進行項目開發時,為了提高項目開發效率,方便項目測試中的局部代碼功能測試會用到單元測試。這樣就不用重新運行一遍整個項目。長期以此我們會就節省大量的時間去做其他的事。首
Android面試准備 第一天 第2-4例
2、如果有個100M大的文件,需要上傳至服務器中,而服務器form表單最大只能上傳2M,可以用什麼方法。個人理解:所謂表單最大只能上傳2M,是不是指一個表單中附件只能上傳
【FastDev4Android框架開發】RecyclerView完全解析之打造新版類Gallery效果(二十九)
(一).前言: 話說RecyclerView已經面市很久,也在很多應用中得到廣泛的使用,在整個開發者圈子裡面也擁有很不錯的口碑,那說明RecyclerVi