android多进程下application初始化,友盟接收推送失败
问题描述
按照友盟官方文档集成了6.1.0的推送,可一直无法接收到推送消息。
问题分析
猜测应该是项目其他代码造成的。但是又没有报错信息。猜测在application中代码有问题,在application中只保留关于推送的代码,发现推送成功。然后放开一部分代码再推送,找到了在application中有初始化webview的操作之后,推送失败。为什么关于webview的初始化会引起推送失败呢。原来是友盟开启了一个新的进程,而在多进程的情况下,每一个进程都会执行一次application。application中初始化webview的代码会执行不止一次。而在9.0以上的系统中,为改善应用稳定性和数据完整性,应用无法再让多个进程共享一个 WebView 数据目录。所以,友盟启动的进程在执行初始化webview操作的时候导致这个进程崩溃,从而无法接收到消息,又不影响主进程的运行,导致肉眼无法观测到。
解决方案
由此可见,每个进程都要执行一次application,那么如果我们不加判断,所有的初始化都要执行多次。所以我们可以通过获取进程名称的方式,判断哪些应该初始化。
@Override public void onCreate() { super.onCreate(); String processName = getProcessName(this); if (processName != null) { if (processName.equals("进程名称")) { //...需要在不同进程下运行的代码 } } } //获取进程名称 private String getProcessName(Context context) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses(); if (runningApps == null) { return null; } for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) { if (proInfo.pid == android.os.Process.myPid()) { if (proInfo.processName != null) { return proInfo.processName; } } } return null; }
主进程的名称是程序的包名,填写包名即可。这样我们一些如用户信息,数据库等操作只在主进程下执行。优化了性能,也避免出现重复执行产生的问题。
由于友盟推送特殊指出了必须在自定义application的onCreate 方法中进行初始化,同时不能对初始化做进程判断,尤其是主进程和channel进程,否则会吐司提示“Toast提示mPushAgent.register should be called in both main process and channel process!”,所以推荐这样进行Application的初始化:
@Override public void onCreate() { super.onCreate(); try { String processName = getProcessName(this); //判断是当前APP进程 if ("主工程包名".equals(processName)) { //app其它资源的初始化 applicationInit(); } //初始化友盟推送、统计不区分进程 initPush(); } catch (Exception e) { e.printStackTrace(); } }
参考资料
https://www.jianshu.com/p/b154dcecd1fd
https://blog.csdn.net/Kebiiii/article/details/77938008
https://developer.umeng.com/docs/67966/detail/67140?spm=a311a.7996332.0.0.6caf3080fk4ltV