作者:极光高级工程师——史坤坤
企业出海图景
在疫情继续,叠加复杂多变的国际贸易环境下,中国对外间接投资流量和存量间断四年稳居寰球前三,近八成中国企业将维持和扩充对外投资动向,看好对外投资前景。企业出海,第一要务就是要建设与用户的触达通道。在APP环境之外,海内触达用户的通道与国内用户略有区别,海内是以邮件为次要的通道,而国内次要是以短信为主,辅以微信等社交通道。在APP环境之内,海内与国内触达用户的区别不大,均是以APP推送为主。接下来,咱们着重从海内APP推送通道来做一些比照与剖析。
APP音讯推送通道现状
在海内,手机厂商除苹果外,安卓依然以三星为领头羊,独占19%的市场份额。小米、OPPO、Vivo、realme紧随其后,市场份额占比别离为12%、9%、8%以及6%。
图一:2021年第四季度寰球智能手机出货量报告(数据来自市调机构Conuterpoint Research)
企业APP的音讯触达用户的通道,最重要的依然还是推送告诉音讯。各个头部厂商对Android原生零碎均有所定制,但与国内环境还是有所区别。
在中国大陆,谷歌受地区限度,无奈应用谷歌相干服务,国内厂商对GMS服务套件进行了零碎层的阉割,谷歌官网的FCM推送通道也相应的无奈应用。进而代替的是各个厂商本人的厂商通道。顾名思义,厂商通道就是指手机硬件厂商提供的零碎级别的推送通道,因为是零碎服务,随着设施开机后就始终存在着,无效的保障了推送通道长连贯的高可用性。
在海内,因为安卓零碎默认反对谷歌FCM通道,且网络环境不受地区限度,因而厂商未对进口海外版的手机进行GMS的阉割,而是保留厂商通道与谷歌FCM通道共存的形式。谷歌FCM通道,是安卓零碎自带的通道服务,与谷歌Firebase后盾放弃长连贯,服务归属是谷歌而非设施厂商。经理论测试、同时与厂商官网技术沟通后,总结对于告诉通道的应用状况如下:
厂商通道与谷歌FCM通道的区别
那么,既然海内的Google服务是不受限制的,为什么厂商还要保留两个通道呢?他们有什么具体的区别吗?的确是存在一些区别。
区别一:就是上边提到的通道归属服务方不同,厂商通道由硬件设施厂商提供服务,谷歌FCM通道由谷歌官网提供服务。
区别二:厂商通道,在网络通顺且推送音讯内容非法的状况下,通过厂商通道推送音讯给该厂商设施,不管利用过程是否存活,都能保障音讯能够推送到位。所以,厂商通道是音讯高效触达的一种保障。同时,也对企业用户的拉活、促新、留存有肯定的晋升。而FCM通道,通过Firebase后盾推送音讯给安卓设施时,设施收到音讯后,会先依据利用的某种状态来决定是否展现音讯。如果APP过程被用户被动杀死,将不会持续进行展现推送音讯。
对于这个规定,起初咱们也是持有狐疑态度,如果这样的话,那与APP本人实现音讯推送相比,就没有高可用的通道服务的劣势了,难道只是为了帮忙开发者简化推送服务的实现流程,升高开发成本?带着这个疑难,咱们开展了专项测试和剖析。剖析过程如下:
- 验证过程存活与被杀死状况下,音讯的展现状况的景象。
- 剖析音讯的生命周期状态
- 深入分析零碎源码、GMS源码、FCM源码
- 总结论断
上面是具体的剖析过程,波及到零碎源码的剖析,如果不感兴趣可略过浏览,间接看最初总结的论断。
01. 验证过程存活与被杀死状况下,音讯的展现状况的景象
a. 退入后盾,无操作停留2小时通过usb连贯手机,进入ADB模式,执行ps命令后,过程依然存在,阐明并未被零碎回收资源。此时发送推送音讯,如预期,告诉音讯失常展现。
b. 退入后盾,通过最近工作,滑动杀死APP
同样,进入ADB后,通过ps命令查看过程状态,过程已不存在,但不确定资源是否被零碎及时回收。此时发送推送音讯,告诉音讯能失常展现。还比拟合乎厂商通道的劣势特色。c. 进入利用详情,强行进行APP
不出预料的,过程必定曾经不存在了,ps命令查看也是如此。同样的,不能确定资源是否被零碎及时回收。此时发送推送音讯,告诉音讯却不能失常展现。由此揣测,FCM通道不依赖APP的过程是否存活。这个特点,是优于APP本人实现推送告诉的。
d. 重启手机
重启手机后,因为利用已没有接管重启零碎的播送权限,过程必定曾经不存在了,同时,资源必定也是被零碎回收了的。此时发送推送音讯,告诉仍然能失常展现。由此进一步确认,零碎缓存了利用的某种状态,FCM会根据该状态来决定是否展现告诉。
02. 剖析音讯的生命周期状态
有了以上试验的景象,那么接下来重点剖析下为什么强行进行APP后,就不能失常收到告诉并展现了。首先看推送API的响应,失常。推送工作已提交至谷歌Firebase后盾,权且认为服务器已下发到设施。通过adb logcat >log.log 抓取现场系统日志,在log中有以下打印:
16600 16600 W GCM : broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=cn.jiguang.junion.jpushtestdemo (has extras) }
确认音讯已失常送达到了设施,因而狐疑GMS的音讯播送就没有失常收回来。
03. 深入分析零碎源码、GMS源码、FCM反编译代码
先依据FCM 办法调用链,从音讯散发处动手往上跟进,确认其调用步骤。
a. FirebaseMessagingService
在零碎源码中跟踪到FirebaseMessagingService 负责散发告诉音讯到SDK。
b. EnhancedIntentService 负责解析解决收到的音讯
c. 持续剖析音讯是哪里接管来的,跟踪到是通过AIDL模式把播送中的音讯传到Service中的
而后发送到FirebaseInstanceIdReceiver
d. 最终的播送起源CloudMessagingReceiver
因而能够明确晓得:FCM 的音讯也是从播送来的。
04. 总结论断
最终,在AMS中找到了答案。利用被用户被动kill后,零碎间接把死亡过程所属的播送,都间接过滤掉了,从而不对其发送播送。
在Android零碎中,利用被用户被动kill后,在ams 中会调用finishForceStopPackageLocked()中 发送外部播送:ACTION_PACKAGE_RESTARTED, 它会限度包的自启或者告诉移除等等。而播送是通过sendBroadcast来发送的,在AMS broadcastIntentLocked 中,明确增加了intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);该Flag后续会从零碎中查找缓存,过滤播送的代码:
registeredReceivers = mReceiverResolver.queryIntent(intent,resolvedType, false /*defaultOnly*/, userId);
在IntentResolver.queryIntent办法外部有调用:
final boolean excludingStopped = intent.isExcludingStopped();if (excludingStopped && isFilterStopped(filter, userId)) { -------这里会过滤Stopped 和过程Stop的 if (debug) { Slog.v(TAG, " Filter's target is stopped; skipping"); }}
isExcludingStopped()的定义代码:
public boolean isExcludingStopped() { return (mFlags&(FLAG_EXCLUDE_STOPPED_PACKAGES|FLAG_INCLUDE_STOPPED_PACKAGES))== FLAG_EXCLUDE_STOPPED_PACKAGES;}
官网的issues也有相似的官网回复,感兴趣的能够看下:
引自:https://github.com/firebase/f...
更多对于海内厂商通道的集成办法,请看下回分解。
对于极光
极光(Aurora Mobile,纳斯达克股票代码:JG)成立于2011年,是中国当先的客户互动和营销科技服务商。成立之初,极光专一于为企业提供稳固高效的音讯推送服务,凭借先发劣势,曾经成长为市场份额遥遥领先的挪动音讯推送服务商。随着企业对客户触达和营销增长需要的不断加强,极光前瞻性地推出了音讯云和营销云等解决方案,帮忙企业实现多渠道的客户触达和互动需要,以及人工智能和大数据驱动的营销科技利用,助力企业数字化转型。