由于谷歌服务在国内不能用,Android 的推送真是一大痛点,但也推动了国内一批做第三方服务的厂商。第三方推送做的比较好的有极光、个推、百度、友盟,经过比较之后,最后选择了极光推送。其实这些第三方推送之间的差别并不太大,技术上都没问题,能不能收到推送,关键还是看前端进程是不是还活着,这也是影响推送成功率的关键。从我们App来看,Android的成功率一直不高,还不到iOS的五分之一。

    前面说了,影响推送成功的关键是前端进程是否活着,App想要收到推送的话,就要一直在后台运行,还有一些流氓软件,为了长期在后台运行,充分利用Android系统的开放性,无所不用其极,这也是早期Android给人体验差的一个重要原因。后来Android系统加强了对后台进程的限制,尤其是国内的手机厂商,在对付国产软件方面,有很高的造诣,甚至有的手机厂商就只给微信开了特权,其他软件到后台几分钟就被杀掉或冻结了。这样用户体验是上来了,但是对于推送来说,真是雪上加霜。

    还好,小米、华为等手机厂商也意识到了这个问题,纷纷推出了自家的推送服务。想从根本上解决Android的问题,还得依赖这些厂商呀!2017年10月16日,工信部也联合国内各大厂商和互联网公司,发起成立了统一推送联盟,致力于解决Android推送问题,统一推送标准,但估计看到成果还需要些时日,远水解不了近渴。于是最近抽时间,研究了华为、小米、OPPO、VIVO这几家国内主流厂商的服务。

    通过对各家推送服务SDK的研究,将分别对每家的推送进行分析,最终给出整合意见。

 


    先放上各家推送服务传送门:华为,小米,VIVO,OPPO。

 华为:

    感觉华为推送的文档比较少,可能跟他的功能太简单有关。首先需要解释下几个名词:Hms(华为移动服务),NC(通知中心)。通知栏推送:即常规的推送,消息抵达时由NC,或者是小米/VIVO/OPPO/等推送服务弹出通知栏。透传:可简单理解为格式自由定义,不弹起通知栏的推送,且透传一般情况下需要在APP处于前后台时才能收到。

    注意,HMS除了支持推送,还支持华为账号登录,华为支付等功能,你可以根据需要自由对接,但因为我们研究的方向问题,这里只讲推送部分。其实在此之前,还有一个老版本的华为推送,但SDK升级后老推送就不再支持,文档也不见了,且新老推送是不兼容的,你只能二选一。

    新的华为推送服务不支持IOS,非华为手机使用华为推送SDK则需要APP各自建立长链接。在非华为手机上首次点开APP后,SDK会引导用户下载华为HMS安装,体验比较差,所以不建议大家在非华为手机上使用该SDK,而且个人尝试了下,虽然下载安装了HMS,但未能在非华为手机成功收到token。

    华为手机使用官方推送的好处是显而易见的,杀掉APP通知栏依然可以收到通知,所有APP共享推送通道,手机更省电,但如果想要使用透传功能,就需要手机处于前后台状态。另外即便是EMUI的手机,也不是接入了SDK就能接收推送了,文档中写到只有部分EMUI4.0和4.1的手机,以及5.0之后的手机才能收到NC服务,其次,删除token和通知栏消息开关的api 在EMUI5.1以上的手机上才能起到效果。最后FAQ中有讲到EMUI8.0目前有个系统底层关于通知栏的bug,请将工程buildVersion、targetVersion和compileVersion都改成26之前的版本。

    那如何分辨手机是否支持华为推送呢,官方FAQ提供了几个方法,点开“在线帮助”-“常见问题说明”中,有具体的EMUI版本及HMS版本的识别方法,这里不再复述。

    服务端API调用有流控限制,用户短时间内发送大量的消息会被流控,并返回HTTP 503状态码。默认3000条/秒,如需要调整,请联系华为客服。并且每次API调用携带的device_token_list最大为1000个推送量,如果你的推送是群发则不用理会这个限制。

    查看文档时,请着重看“开发准备”,和“客户端开发指南”,两处的文档描述很详细。

    集成SDK时还有一点需要注意,除了使用gradle集成SDK,还需要下载一个hms agent压缩包,这个压缩包其实就是一些华为的代码,可能官方觉得把所有功能都整合到SDK里太大了,就用这种方式希望大家按需解压,但个人感觉其实没什么必要。解压后的根目录中有readme文件,建议仔细阅读,如果你是windows,请点击bat文件,执行后根据提示按需选择即可,最终把提取出来的java文件放入工程目录里。

    在完成开发者账号申请,创建APP,集成SDK,修改manifest等准备工作后,你就可以尝试推送一条消息给手机了。

    其实接入推送SDK,我们开发人员关心的无非三件事,一是如何获取token/regid,二是通知消息怎么回调,三是推送格式怎么写。

    首先token方面,华为SDK是异步获取,即调用gettoken方法后,方法内部最多只返回成功失败的状态码,只有在自定义消息接收器里才能收到token值。而我们常用的极光SDK,则是同步方法:getregid,直接返回空或者具体值。这是他们之间的差异。

    接下来说下华为推送消息回调,这里有些坑需要注意。目前自定义的接收器,只能接受两个回调信息,onEvent和onPushMsg,前者是通知栏消息的回调,后者是透传的回调。但通知栏回调在通知消息到达时是无法收到的,无论前后台都不行,只有用户点击了携带附加消息的通知,onEvent才能触发正常,而透传之前说过了,必须在前后台状态才可以,所以如果大家收不到推送到达的回调,不要着急,SDK就是这样设计的。

    其实接入到这里,感觉华为这个推送SDK设计的很别扭,相信很多开发者是需要收到推送的时候在APP执行一些操作的,但是华为的推送不支持,用户不点击通知栏,即便应用处于前台,你也永远不知道这条推送到达了。所以如果大家用推送到达的回调来处理一些业务逻辑的话,建议发送通知栏消息的时候,再叠加一条透传用于业务处理。

    而推送格式方面,华为支持比较有限,通知栏推送只能指定打开APP(即首页,大部分APP首页都是闪屏),或者打开特定页面,不够灵活。譬如我们的使用场景是根据接受的推送信息分别跳转至ABC等页面,使用极光就可以自己在receiver里自由处理,而华为只能用两种方式,一是指定通知栏点击动作为打开APP,同时对scheme添加附加信息或对推送添加extra,在启动页根据获取到的附加信息进行处理;二是按照scheme协议的格式,在我们的app的manifest里每个要跳转的页面都加入scheme,后台推送时候针对发送即可。或者将两个思路融合,创建一个透明样式的activity,每次推送我们都指向该页面,然后再解析附加信息按需跳转即可。而且用这种方式的好处是不用在onEvent里处理回调。

小米:

    小米文档感觉非常详细全面,阅读完之后感觉和极光差不多,如果你熟悉极光推送,那么小米推送接入的应该会很快,而且原有逻辑部分几乎不需要修改。小米推送的优势是,在MIUI中所有APP共享推送通道,APP被杀死也依然能收到通知,除此之外还支持u3d,python等sdk,还有花哨的呼吸灯等推送配置。而且小米推送也是支持IOS的,所以理论上,如果你没有使用其他的统计崩溃统计等功能的话,完全可以用小米推送替换掉极光,友盟等。

    因为小米文档十分完善,这里直接从系统判断,token获取,回调方式,推送格式四方面分析。

    判断MIUI,直接在文档中心搜索“如何识别小米设备/MIUI系统”即可,官方文档会告诉你答案。

    token上,小米提供了同步的MiPushClient.getRegId的同步方法,以及recevier接收两种方式。使用比较灵活。

    消息回调上,onNotificationMessageArrived在推送消息到达时触发,onNotificationMessageClicked则在用户点击通知栏时触发,onReceivePassThroughMessage在透传消息到达时触发,但是需要注意,透传依然需要APP处于前后台状态时候才能回调。而通知栏消息到达回调,只有APP在前后台才能收到,在APP杀死后重启,不再能回调成功。

    推送格式上,小米除了提供了像华为一样的,打开APP,打开指定页面(scheme格式)外,还有自定义模式,自定义模式就是用户点击通知栏后,打不打开页面,打开什么页面,完全由开发者在receiver收到回调后自己处理。

    另外,小米推送的功能比华为强大不少,支持分组,别名等功能。后台API调用次数按照文档说法,目前没有限制,但是如果是针对regid推送,每次API调用最多只能携带1000个。

VIVO:

      vivo的推送文档是pdf格式,需要下载。按照文档,vivo推送目前只支持自家rom,而在token获取,回调,推送格式上,和极光小米也是类似的。

    但是对于vivo推送,有一些需要注意,点我--push推送--push接入FAQ中,有几个关键点,一个是目前vivo推送不支持接入金融类服务!二是支持vivo push的vivo 机型特别少,对,你没看错,vivo自己家的推送服务,就支持那几款手机而已。

    不过SDK提供了识别手机是否支持vivo推送的方法,使用PushClient.getInstance(application).isSupport()或者是判断回调状态码101均可。经个人尝试,找到了若干款型号类似的手机,譬如文档中讲支持VIVO X21手机,但是我用X21A就不支持推送,可见这个局限性还挺大。因为找不到符合条件的手机,目前只是把代码整合进去了,具体还没进行测试。

    token获取提供了PushClient.getInstance(application).getRegId()同步方法,onReceiveRegId回调方法,但文档描述这个回调仅仅在regid变化时可收到。

    onNotificationMessageArrived回调在推送到达时触发,onNotificationMessageClicked回调在推送点击时触发,因为没有真机测试成功,在杀死APP重启后是否能继续收到未经验证。

    而且即便大家整合完毕,也需要留意,官方文档中描述,VIVO推送是分时段的,为了避免打扰用户,目前vivo手机接收的消息为9:00-21:00,服务器允许推送时间为9:00-20:00,单推不受此时间限制。限制时间外的推送将被作废,不再重发。所以需要整合的小伙伴要权衡。

OPPO:

    oppo推送目前处于公测阶段,打开就会提示只对部分开发者开放,至于如何成为部分受邀开发者,需要通过邮件进行申请,但是到哪里申请不知道。这里也没有往下进行了。但想到OV(OPPO和VIVO,以下简称OV)其实是一个老板,而且看VIVO那边的情况,差不多也就明白了,OV的推送服务应该是刚开始起步,估计只有部分新款手机才能支持,虽然OV手机的用户占比比较高,但是能收到推送的新机型比例应该还是很低的。所以目前是否需要接入看大家各自需要。

推送整合 :

    老牌三方推送,极光SDK也支持各家推送通道进行整合,就类似sharedsdk整合分享原理一样,前提是需要分别注册各家大厂的推送账号,创建应用。最后按极光的文档配置各种appid,appkey即可,但是极光的该功能是收费服务,具体费用需要咨询极光商务。而自己整合肯定没有费用问题。

    单独接入各家SDK的最终目的还是要整合在一起,按照目前的粗略调查,OV的ROM占比高达45%以上,还是很可观的,如果加上华为,小米,四家厂商的ROM会高达85%+,整合后的效果会比单纯集成极光好很多。魅族也有推送,但是比例低于1%,三星及其它手机则更低,所以就没有关注其他的推送。

    整合的意义在于提高推送到达率,更加省电。 由于目前的OV推送服务有很大的不确定性,建议不是特别紧急就不用集成了,保持关注即可,毕竟随着时间的推移,支持OV推送的手机比例会大幅度增加,届时再接入也不迟。

    目前整合的大致思路是首先识别ROM,依据rom类型分别启动不同SDK(前边已经介绍了各个厂商识别自家ROM的方法),如果无法成功识别或者启动SDK异常,则使用极光等三方推送或小米推送作为兜底。

    第二是获取不同厂家的token/regid,上报给自己的服务器进行绑定,因为有的厂家是异步,有的是同步获取,需要大家视情况自己处理业务逻辑。

    第三由服务器针对APP上报的信息,使用不同厂家的推送API推送信息。推送方式和格式上建议统一,即创建一个透明activity,统一使用scheme格式并携带附加信息,看起来大概是这个样子:你定义的scheme:你定义的host?action=你定义的action,然后在透明的activity里根据action跳转至不同页面,处理完成后及时关闭这个透明界面即可。

   

Q&A :

Q: 消息“送达率”是100%的,如果做不到100%,那么服务就是有问题。 

A: 其实不是的,即使是成功率非常高的短信(SMS),送达率也做不到100%,总有关机的用户吧?总有废弃的号码吧?消息推送的技术原理是要依赖于稳定的长连接通道,受网络、后台Service、系统以及厂商ROM等多重限制,很难做到100%。有经验的开发者伙伴一定知道,App的送达率其实是和App自身的日活正相关的,可以想想App自身是不可能有很高的日活用户比例(微信这类超高频App除外),所以App的送达率也是一样的道理。关于送达率的解释,请参考这个帖子: “谈谈消息推送的送达率”

Q: 我在服务器端发送了10W条消息,最终统计到的收到数是4W,那么送达率就是40%了? 

A: 不是的,这里其实还是要看看送达率的概念,参照 “谈谈消息推送的送达率”,这里一个核心问题就是分母怎么定义。一般来说,开发者发送到友盟的设备,友盟服务器还要做有效性判定(比如device token是非法的,token发生了变化,旧token已经失效等),真正发送的对象是链接里面提到的“有效数/接收数”,分母要按照“接收数/有效数”来计算。

Q: 我手头两个机器测试,发现有1部手机总是收不到消息,那么送达率只有50%? 

A: 样本太少了,任何XX率的计算,肯定要有一个非常大的样本集合。由于国内Android机型的碎片化现象,不同厂商上推送服务的表现可能区别会很大,经常会出现推送服务在某些机型上工作的比较正常,有某些机型表现不太好的现象,友盟+Push SDK要做的就是尽可能去适配各种机型,保证在大部分情况下均可以正常work。如果要评估送达率,最好是能灰度发布一批线上设备,针对这批灰度的量做一下实际测试,这样得到的结论会准确一些。

Q: 在三星手机上App退到后他是能收到消息的,但是在小米手机上App退到后台就收不到消息了,是不是push sdk有问题? 

A: 不是的,这种情况下一般是用了小米系统的“一键清理”功能,把App进程清理了。MIUI上对推送服务做了限制,如果App被杀死了,是不允许收到消息的。这个是系统的限制,不是Push SDK的问题。常见特殊机型整理见这里。

Q: 集成了友盟推送,测试了强杀App,断网恢复网络,发现消息有的时候收不到,是不是Push SDK有问题? 

A: 不一定是Push SDK的问题,如上个问题所述,有的时候是系统或者厂商ROM自身会做一些限制,比如App被强杀掉,对应的push service也会被清理掉,有的时候是push SDK的一些策略,比如考虑到省电的因素,长连接的心跳探测不一定非常频繁,导致断网重连不一定能及时感知到。这里也建议开发者测试的时候,尽量先保证SDK能在正常情况下工作,之后再去测试像"强杀、一键清理、网络切换、开机重启"之类的测试用例,不同机型表现都不太一样,大家可以在我们文档或者论坛上多搜搜已归档的问题或者解决方案。

Q: 只要集成了友盟推送,在任何情况下均可以收到消息。 

A: 不是的,如前面问题所述,推送是有送达率的概念的,以及在客户端上,系统、网络等多方面的影响因素均会影响到消息的成功接收。

Q: 我的设备是联网了,那就表示“设备在线”了,应该能收到推送消息吧? 

A: 不是的,“设备长连接”在线是消息能顺利下发的前提,“设备长连接”在线的含义是: 1. 设备联网;2. 设备上的Push Service存在; 3.Push Service与服务器端已经建立起长连接通道。有了这3点保障,才算是“设备长连接在线”。设备联网只是其中一个必要条件。

Q: 服务器端调用推送API显示成功了,客户端也会同步收到消息。 

A: 参考这个帖子: “调用服务器端API接口返回成功,为什么客户端没收到消息?”

Q: iOS推送和Android推送原理是一样的。

A: 本质上,技术原理是一样的,都要用到长连接技术。实际在实现上,Android是友盟自建推送系统,iOS用的是苹果官方的APNs(Apple Push Notification Service)系统。

Q: Android平台的推送提供“收到”、“打开”和“忽略”数字,iOS平台也会提供。 

A: 不是的,接上一个问题,因为苹果使用的是APNs推送,苹果只开放“打开”这个接口,所以iOS平台我们提供 “推送到APNs数”和“打开数”,iOS平台目前是统计不到消息送达的。

Q: Android推送平台,推送完消息后,过了3个小时设备才收到,这延迟太大了。。。 

A: 不是的,目前系统能做到,在“设备在线(设备联网&长链接PushService存在&与服务器端建立了长连接通道)”的情况下,即发即到。 如果出现长时间的延迟,可能发消息的瞬间,设备的长连接Service不存在,或者存在的话,可能没有和服务器端建立通信连接,后来设备在线了,之前保存的离线消息又下发下去了。可以参照“设备状态离线排查”

Q: 调用服务器端API接口成功,但是实际上设备没收到消息,是不是友盟推送服务出问题了呢, 是延迟吗?

A: 不是的,请参考“API返回接口成功,但是设备端没有收到消息原因排查”

Q: Android推送连续发送了好几条,发现客户端只收到了一条,是不是消息有丢失呢? 

A: 不是的,我们在客户端做了体验优化,如果使用默认通知栏样式,同时送达多条消息的时候,默认是只展示最后一条通知。如果想要展示多条消息,请在SDK集成文档中找一下对应的设置方法。

 

保活方案大汇总

android9.0系统下,讨论如何延长APP退到后台的保活/复活时间

一、7.0及以上不存在真正意义的保活。

二、盘点目前在9.0上,可能有效的“白色手段”保活手段(这里不讨论黑色和灰色手段)。

1.仿TIM引导用户打开“后台自启动”和加入“手机白名单”。

测试开始后台自启动,测试通知栏多久还能收到通知

华为M10 9.0

时长3到5小时没被杀死

VIVO x23 9.0(数字以分钟计算)

1 Y收到

2 Y

3 Y

6 Y

8 通知栏已无通知(app被系统杀死)

10 N收不到

抛出问题:使用H5界面引导用户打开后台自启动,用户如果会同意吗?

2.开启前台服务,会生成多余的通知,被产品否定

3.优化应用内存,正在进行中...

4.仿网易云音乐,复写锁屏界面。

5.集成华为/小米/oppo/vivo/魅族手机系统级推送。

6.集成“信鸽/个推/极光/友盟等”第三方推送,以期达到关联启动。

三、盘点已经失效或者不适合的保活黑科技,这里的“不适合”是因为我们做政府项目,后台是布在内网上的。

1.双进程守护方案,华为6.0就失效

2.监听锁屏/亮屏/解锁广播,打开1像素Activity,华为6.0就失效,因广播被取消了

3.故意在后台播放无声的音乐,华为M10手机9.0失效

4.使用JobScheduler唤醒Service,7.0以上失效

5.集成华为/小米/oppo/vivo/魅族等push,因为项目本地化部署,不适合

6.推送互相唤醒复活:极光、友盟、以及各大厂商的推送,因为项目本地化部署,不适合

7.同派系APP广播互相唤醒:比如今日头条系、阿里系,因为项目本地化部署,不适合

8.使用自定义锁屏界面:覆盖了系统锁屏界面。网易云音乐就是如此,但是会生成一个常驻通知栏的通知

9.把APP设置为系统应用,不适合,因为需要权限等

10.native进程(已报废)

11.利用账号同步机制拉活,失效了

12. 提高Service优先级,比如onStartCommand返回START_STICKY,没什么效果

四、总结

问:为什么需要保活

答:作为IM聊天软件,希望能即时收到好友消息。

问:为什么保活失败?

答:因为点击home键使app长时间停留在后台,内存不足被kill;

进入锁屏状态一段时间,省电机制会kill后台进程。

 


 

更多相关文章

  1. Android消息机制Handler的实现原理解析
  2. Android消息机制,从Java层到Native层剖析
  3. Umeng推送消息的坑,Android Service的android:exported详解
  4. Android消息机制-深入理解消息队列的工作模式
  5. Android应用程序的消息处理机制
  6. Android消息机制初步分析
  7. Android消息提示框和对话框的使用

随机推荐

  1. ScrollView嵌套RecyclerView出现item显示
  2. Android———利用JDBC连接服务器数据库
  3. 搜索框(SearchView)用法
  4. Android(安卓)三种播放视频的方式
  5. Android(安卓)Paint之PathEffect(路径效
  6. 反编译apk文件,得到其源代码的方法
  7. AndroidStudio使用[原创]
  8. Android(安卓)RecyclerView与ListView局
  9. Android常用控件之FragmentTabHost的使用
  10. 1.1安卓系统架构