记一次sharedUserId引起的友盟推送无效问题
一、项目背景
应用于车载设备的广告终端App,集成于系统应用apk;有新的产品需求,初期调研时使用友盟推送sdk,在手机端以及在普通apk模式的时候,接入推送正常无误;后续直接开发对应推送业务逻辑,直到QA测试阶段,发现问题;
二、问题描述
作为普通apk时,AndroidManifest中配置和普通手机apk模式一样,接入友盟sdk,6.2.x,也是最新版了(2021/04/26)按照官方文档,接入正常,服务端发送推送(通知,消息,透传)都是可以的。
-
将apk改为系统rom签名的,同时配置AndroidManifest中
android:sharedUserId="android.ui.system"
之后,也就是将app和系统应用一个权限了。此时,运行apk,友盟的进程
:channel
是存活的,但是后端推送消息,无法接收到,不论是友盟官方推送,还是api调用方式,都无效;- 同时会有warn警告日志Calling a method in the system process without a qualified user,这个是ContextImpl中警报的,可查看源码,(2280行,似乎是)并没有return拦截掉流程,也就是说,这个warn不会影响运行;
- 上述警告的原因在于,系统uid的应用自身调用activity、service、broadcast的时候,会有这个警报;经自写demo测试,会出现这个警报问题,但不影响程序。
- 上一条中,如果service、receiver等尚未启动过,则其他进程调用是无效的;这个是核心!
三、问题分析排查
如上定位问题概述,是由于apk配置了sharedUserId
引起友盟推送sdk收不到消息,内部核心实质很难排查,友盟的sdk是混淆的,调试起来相当费时;
断断续续一周多,都在反复验证和调试定位问题,可以大致结论:
- 友盟推送sdk(项目所指版本)在sharedUserId模式下,App运行起来后,其后台的长链接是通的,推送下发的指令信息应该也是到达sdk终端的;
- sdk终端内部会解析信息,有专门的service服务,receiver来重构解码后的数据给客户端apk;
- 经反复对比排查验证试验,上一条所指解析数据的receiver或service应该是没有启动成功(在sharedUserId模式下),所以其他进程调用该服务也是无效的。(见第二条的最后一个点描述)
四、问题解决方案
经对比,腾讯推送无此问题,可以替换业务方案;
-
变相的,复杂的解决方案
- 创建一个非sharedUserId的sub apk,集成友盟的推送,并处理相关消息指令
- 主apk与sub可以用进程间通信aidl或者广播也行,交换信息,使得主apk响应到推送指令
副作用,这样就要考虑把sub及时启动,并设法保持存活进程;(可通过主apk的启动调用,定时轮训存活状态等);
如此对比直接内嵌sdk来说,业务复杂,推送到达率不能保证了。
-
类似于上一条,sub apk也是集成友盟推送sdk,主apk也集成,并且推送消息逻辑在主apk内完成;
要求点,sub中的友盟推送的service和receiver指定的process为单独的,而非
:chanel
带冒号的那种子进程;主Apk中的友盟推送service和receiver也是指定process和sub的一样;
这样启动sub就会启动推送process,也变相启动了主apk的推送process,就能接受不了到信息了。(原因在第二条的最后一点)
后记:如上仅为指定友盟推送sdk的版本,在特定rom上,作为系统应用apk的场景下遇到的问题;分析排查的原因总结,也未必抓住了问题的本质核心。这里作为笔记,以留后验。