Android項目實戰--手機衛士28--讀取進程的信息並顯示出來



最新實戰教程,讓你瞭解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



今天源碼下載



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章