Android多版本獲取當前進程名兼容性方案

1、背景

項目中的路由框架中,須要獲取到當前的進程名,一開始經過經常使用的ActivityManager.getRunningAppProcesses()寫法,上線後發現有必定隨機機率的異常發生,致使業務邏輯出現問題。經查,不一樣的Android版本和機型上,此方法調用確實有可能機率性拋出異常。android


2、處理

爲兼容各個不一樣的版本和機型,獲取進程名能夠從多個不一樣維度分別進行,最後封裝成工具庫供上層調用。且考慮到進程名的變量屬性,經過定義靜態變量將其進一步做緩存化處理,減小沒必要要的調取過程。緩存

最終封裝後的工具類以下:markdown

public class ProcessUtil {
    private static final String TAG = "ProcessUtil";

    private static String sProcessName = "";

    private ProcessUtil() {

    }

    public static String getCurrentProcessName(Context context) {
        if(!TextUtils.isEmpty(sProcessName)) {
            return sProcessName;
        }

        try {
            sProcessName = getCurrentProcessNameByActivityManager(context);
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

        if(!TextUtils.isEmpty(sProcessName)) {
            return sProcessName;
        }

        try {
            sProcessName = getCurrentProcessNameByApplication();
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

        if(!TextUtils.isEmpty(sProcessName)) {
            return sProcessName;
        }

        try {
            sProcessName = getProcessNameByCmd();
        } catch (Exception e) {
            Log.e(TAG, e.toString(), e);
        }

        if(!TextUtils.isEmpty(sProcessName)) {
            return sProcessName;
        }

        try {
            sProcessName = getCurrentProcessNameByActivityThread();
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

        return sProcessName;
    }


    public static String getCurrentProcessNameByActivityManager(Context context) {
        int pid = android.os.Process.myPid();
        ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                return appProcess.processName;
            }
        }
        return null;
    }

    public static String getCurrentProcessNameByApplication() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            return Application.getProcessName();
        }
        return null;
    }


    public static String getProcessNameByCmd() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("/proc/" + android.os.Process.myPid() + "/cmdline"));
            String processName = reader.readLine();
            if (!TextUtils.isEmpty(processName)) {
                processName = processName.trim();
            }
            return processName;
        } catch (Exception e) {
            Log.e(TAG, "getProcessName read is fail. exception=" + e);
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                Log.e(TAG, "getProcessName close is fail. exception=" + e);
            }
        }
        return null;
    }

    public static String getCurrentProcessNameByActivityThread() {
        String processName = null;
        try {
            final Method declaredMethod = Class.forName("android.app.ActivityThread", false, Application.class.getClassLoader())
                    .getDeclaredMethod("currentProcessName", (Class<?>[]) new Class[0]);
            declaredMethod.setAccessible(true);
            final Object invoke = declaredMethod.invoke(null, new Object[0]);
            if (invoke instanceof String) {
                processName = (String) invoke;
            }
        } catch (Throwable e) {
            Log.e(TAG, e.toString());
        }
        return processName;
    }
}
複製代碼
相關文章
相關標籤/搜索