如何優雅獲的獲取不同系統版本中的程式資訊

maweiliang發表於2019-03-04

今天來總結一下獲取系統中正在執行的程式資訊,直接來乾貨
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;
           }複製程式碼

相關文章