Android 多进程导致 Application 重复创建问题

背景

一般情况下,一个应用程序就一个进程,这个进程的名称就是应用程序包名。Android 的四大组件在 AndroidManifest 文件中注册的时候,有个属性是 android:process,这里可以指定组件的所处的进程。

一个进程情况下,Application 的 onCreate 方法只会执行一次,但如果应用中采用多进程方式,onCreate 方法会执行多次。

解决方案

获取当前运行进程的名称:

方案1

public static String getProcessName(Context cxt, int pid) {  
    ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);  
    List<RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();  
    if (runningApps == null) {  
        return null;  
    }  
    for (RunningAppProcessInfo procInfo : runningApps) {  
        if (procInfo.pid == pid) {  
            return procInfo.processName;  
        }  
    }  
    return null;  
}  

方案2
方案二比较快速

public static String getProcessName() {
  try {
    File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
    BufferedReader mBufferedReader = new BufferedReader(new FileReader(file));
    String processName = mBufferedReader.readLine().trim();
    mBufferedReader.close();
    return processName;
  } catch (Exception e) {
    e.printStackTrace();
    return null;
  }
}

然后在 Application 的 onCreate 中获取进程名称并进行相应的判断,例如:

String processName = getProcessName(this, android.os.Process.myPid());

if (!TextUtils.isEmpty(processName) && processName.equals(this.getPackageName())) {//判断进程名,保证只有主进程运行
	//主进程初始化逻辑
	....
}

完整使用案例

public class MyApplication extends Application {

    private static String sCurProcessName = null;
    private String processName;
    private String packageName;

       1.  Application的attachBaseContext方法是优先执行的;
       2. ContentProvider的onCreate的方法 比 Application的onCreate的方法 先执行;
       3. Activity、Service的onCreate方法以及BroadcastReceiver的onReceive方法,是在MainApplication的onCreate方法之后执行的;
       4. 调用流程为: Application的attachBaseContext ---> ContentProvider的onCreate ----> Application的onCreate ---> Activity、Service等的onCreate(Activity和Service不分先后);

    @Override
    protected void attachBaseContext(final Context base) {
        super.attachBaseContext(base);
        processName = getCurProcessName(base);
        packageName = getPackageName();
        boolean isMainProcess = !TextUtils.isEmpty(packageName) && TextUtils.equals(packageName, processName);
      
        if (isMainProcess) {

        } else if (isPushProcess()) {

        } else if (isGameProcess()){

        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    private static String getCurProcessName(Context context) {
        if (!TextUtils.isEmpty(sCurProcessName)) {
            return sCurProcessName;
        }
        sCurProcessName = getProcessName(android.os.Process.myPid());
        if (!TextUtils.isEmpty(sCurProcessName)) {
            return sCurProcessName;
        }
        try {
            int pid = android.os.Process.myPid();

            sCurProcessName = getProcessName(pid);
            if (!TextUtils.isEmpty(sCurProcessName)) {
                return sCurProcessName;
            }
            //获取系统的ActivityManager服务
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            if (am == null) {
                return sCurProcessName;
            }
            for (ActivityManager.RunningAppProcessInfo appProcess : am.getRunningAppProcesses()) {
                if (appProcess.pid == pid) {
                    sCurProcessName = appProcess.processName;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sCurProcessName;
    }

    private static String getProcessName(int pid) {
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
            String processName = reader.readLine();
            if (!TextUtils.isEmpty(processName)) {
                processName = processName.trim();
            }

            return processName;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return null;
    }


    private boolean isPushProcess() {
        return !TextUtils.isEmpty(packageName) && TextUtils.equals("com.ai.test:pushservice", processName);
    }

    private boolean isGameProcess() {
        if (TextUtils.isEmpty(packageName)) {
            return false;
        }
        if (TextUtils.equals("com.ai.test:game", processName)) {
            return true;
        }
        return false;
    }


}

版权声明:本文为qq_34681580原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。