今天來總結一下獲取系統中正在執行的程式資訊,直接來乾貨
4.X系統中:
public List<ProcessInfo> getAllRunningAppProcessInfo() {
ActivityManager am = (ActivityManager) GTApp.getContext()
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcessList = am
.getRunningAppProcesses();
List<ProcessInfo> ret = new ArrayList<ProcessInfo>();
for (ActivityManager.RunningAppProcessInfo info : appProcessList)
{
ProcessInfo processInfo = new ProcessInfo(info.pid, info.processName, -1, info.uid);
ret.add(processInfo);
}
return ret;
}複製程式碼
5.x系統中:
5.0系統以上am.getRunningAppProcesses()方法就不能獲取系統正在執行程式的相關資訊,只能返回本應用程式的程式。我們可以通過ps的相關方法獲取。
1.ps |grep zygote命令獲取android應用程式的父程式Zygote的程式號
從Android 4.4宣佈支援64位系統以來,各終端方案廠商逐步推出了各自的64位soc解決方案。Google為了相容之前32位系統的應用,在64位系統上也實現了對32位應用的支援,在64系統中會同時存在兩個Zygote程式——zygote和zygote64,分別對應32位和64位應用。所以,要進行App的32/64位檢測,只需要看它的父程式是哪個Zygote即可
public List<ProcessInfo> getAllRunningAppProcessInfo() {
List<ProcessInfo> appProcessList = new ArrayList<ProcessInfo>();
// 先取Android應用程式的父程式zygote的程式號,64位app對應的是zygote64
int zygotePid = -1;
int zygotePid64 = -1;
BufferedReader readerZ = null;
try {
ProcessBuilder execBuilderZ = null;
execBuilderZ = new ProcessBuilder("sh", "-c", "ps |grep zygote");
execBuilderZ.redirectErrorStream(true);
Process execZ = execBuilderZ.start();
InputStream isZ = execZ.getInputStream();
readerZ = new BufferedReader(
new InputStreamReader(isZ));
String lineZ = "";
while ((lineZ = readerZ.readLine()) != null) {
String[] arrayZ = lineZ.trim().split("\s+");
if (arrayZ.length >= 9) {
if (arrayZ[8].equals("zygote"))
{
zygotePid = Integer.parseInt(arrayZ[1]);
}
else if (arrayZ[8].equals("zygote64"))
{
zygotePid64 = Integer.parseInt(arrayZ[1]);
}
}
}
}
catch (Exception e) {
e.printStackTrace();
} finally {
FileUtil.closeReader(readerZ);
}
if (zygotePid < 0)
{
return appProcessList;
}複製程式碼
2.正式的獲取正在執行的程式資訊:
BufferedReader reader = null;
try {
ProcessBuilder execBuilder = null;
execBuilder = new ProcessBuilder("sh", "-c", "ps |grep u0_a");
execBuilder.redirectErrorStream(true);
Process exec = null;
exec = execBuilder.start();
InputStream is = exec.getInputStream();
reader = new BufferedReader(
new InputStreamReader(is));
String line = "";
while ((line = reader.readLine()) != null) {
//使用多個空格分隔
String[] array = line.trim().split("\s+");
if (array.length >= 9) {
//大於10000的uid會以u0_a開頭,10021顯示為u0_a21
//非系統應用的名稱已U0_a開頭,使用者的uid都大於10000,
int uid = Integer.parseInt(array[0].substring(4)) + 10000;
int pid = Integer.parseInt(array[1]);
int ppid = Integer.parseInt(array[2]);
// 過濾掉系統子程式,只留下父程式是zygote的程式
if (ppid == zygotePid || ppid == zygotePid64)
{
ProcessInfo pi = new ProcessInfo(pid, array[8], ppid, uid);
appProcessList.add(pi);
procInfoCache.put(array[8], pi);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally
{
FileUtil.closeReader(reader);
}
return appProcessList;
}複製程式碼
6.x以上系統:
static class Process6x extends Process5x
{
// 有的6.x系統,在ps命令的策略上和5.x還是一樣的,此時應該用5x的策略
static boolean isLike5x = false;
@Override
public List<ProcessInfo> getAllRunningAppProcessInfo() {
if (isLike5x)
{
return super.getAllRunningAppProcessInfo();
}
List<ProcessInfo> appProcessList = new ArrayList<ProcessInfo>();
// 正式取可用的Android程式
BufferedReader reader = null;
try {
ProcessBuilder execBuilder = null;
execBuilder = new ProcessBuilder("sh", "-c", "ps");
execBuilder.redirectErrorStream(true);
Process exec = null;
exec = execBuilder.start();
InputStream is = exec.getInputStream();
reader = new BufferedReader(
new InputStreamReader(is));
String line = "";
while ((line = reader.readLine()) != null) {
String[] array = line.trim().split("\s+");
if (array.length >= 9) {
// 先遮蔽常用的shell命令程式
if (array[8].equals("su") || array[8].equals("sh")
|| array[8].equals("sush") || array[8].equals("ps"))
{
continue;
}
int uid = -1;
try
{
uid = Integer.parseInt(array[0].substring(4)) + 10000;
}
catch (Exception e)
{
// 如果異常了,說明取到了系統程式資訊,則判定為該6.x系統的策略和5.x一致,應嘗試5.x的策略
isLike5x = true;
FileUtil.closeReader(reader); // 提前關閉流
return super.getAllRunningAppProcessInfo();
}
int pid = Integer.parseInt(array[1]);
int ppid = Integer.parseInt(array[2]);
ProcessInfo pi = new ProcessInfo(pid, array[8], ppid, uid);
appProcessList.add(pi);
super.procInfoCache.put(array[8], pi);
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally
{
FileUtil.closeReader(reader);
}
return appProcessList;
}複製程式碼