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;
    }
}
复制代码
相关文章
相关标签/搜索