最新實戰教程,讓你瞭解Android自動化刷量、作弊與防作弊的那些事,案例:刷友盟統計、批量註冊蘋果帳號
今天呢,我們就繼續我們的進程管理啦,昨天我們就講到了拿到進程數目,以及可用的內存,那麼今天,我們就把那些進程一個個的顯示出來,
但在做今天這個之前,我先給大家提個醒,我覺得那個程序鎖的界面有點不好看,所以就修改了一下,大家到時可以看看源碼,我們就先把今天要做的,和那個程序鎖的給大家看看先吧
大家可以看到,我們這個界面也是挺簡單的,有一個標籤把系統的進程和用戶的進程給區分開來,所以我們到時在顯示在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;
}
}
好啦,寫完model類之後,我們就要寫一個類來讀取我們的進程信息啦
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;
}
}
讀取進程的信息,其實也很簡單的,我們上一次已經拿到了RunningAppProcessInfo的集合啦,那麼我們只要遍歷這個集合,那就可以拿到這些進程啦,
那麼,我們就可以讀取到它們的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();
}
完成加載之後,就會發送一個消息給handler,然後就進來顯示的操作的
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;
}
}
};
那麼,接下來,我們就是要進行我們最麻煩的那個操作啦,就是listview的操作啦,也就是adapter的編寫啦
因爲我們要區分系統進程和用戶進程嘛,還要加兩個標籤,所以那就處理起來有點麻煩的啦
首先,我們要區分系統進程,和用戶進程,那麼我們就用兩個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);
}
}
}
因爲我們要加兩個標籤來顯示是用戶進程還是系統進程嘛(也就是兩個TextView),所以返回的條目就要加2啦
@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;
}
}
最後,就是我們的getView方法啦,這個是非常的重要的,關係到我們的顯示
@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;
}
在裏面,我們用到一個生成TextView的方法
private TextView newTextView(String title)
{
TextView tv_title = new TextView(ProcessManagerActivity.this);
tv_title.setText(title);
return tv_title;
}
好啦,這個adapter比較複雜,不像我們之前寫的那樣,直接顯示就行啦,這次,多了很多判斷,但實際開發中,這種情況是很常見的,所以大家最好懂得這樣來定義自己複雜的adapter,不然就會很麻煩的了
如果對上面代碼有什麼不明白的,可以說出來
好啦,寫到這裏,我們的邏輯就基本上完成的啦,下面把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