起因:做了两个带推送的app:HiApp和WeApp,前者个推,后者百度推送,但前者有一个小缺陷。
现象:两部手机
1.htcD820t手机,运行中的app利用自带的关闭最近程序后,通知栏不清理该app的推送消息,但点进去无反应。
2.红米:手机的设置中关闭进程,通知栏没有清除,点击进去无反应,进入不了该消息对应的app。利用小米自带的清理或第三方清理内存后,通知栏消息全都被清掉。
但是WeApp不会出现上述问题。个推demo与该app一样现象。
个推demo现象:htcD820t手机
1.应用关闭--发送推送--demoApp收到推送--点击通知栏demoApp启动
2.应用开启--发送推送--demoApp收到推送--手机长按menu等的最近程序清理--点击通知栏demoApp未启动,没有任何反应。
从log看,个推是收取推送是一个Receiver,然后收到后在sdk创建的通知。点击通知栏在发送广播,然后自己程序中的MyPushPeceiver此时收广播跳转,两次广播的处理。那上面第2中现象是因为这个第二次的广播发出时app已经被清理了?这个自定义的PushPeceiver继承自BroadcastReceiver并注册在application中,并不是推送服务中的。从log上看是没有收到广播。(此处有疑问,整理了另一篇介绍PendingIntent和BroadcastReceiver的:Android基础知识巩固:关于PendingIntent和广播
)。
后来看到官网的一个介绍:registerReceiver的官方文档介绍里:
Note: this method cannot be called from a BroadcastReceiver
component; that is, from a BroadcastReceiver that is declared in an application's manifest. It is okay, however, to call this method from another BroadcastReceiver that has itself been registered at run time withregisterReceiver(BroadcastReceiver, IntentFilter)
, since the lifetime of such a registered BroadcastReceiver is tied to the object that registered it.
大意是:如果一个BroadcastReceiver是在manifest文件中注册的,它就不调用registerReceiver方法。但是如果是在运行时注册的BroadcastReceiver就可以调用,因为这样注册的广播的生命周期是绑定到注册的对象的。
没有太明白,是否和这个有关。因为创建通知栏的那个广播一般是在manifest中注册的,这里不能再广播发送广播了么?
TODO:按道理,通知栏pendingIntent发广播的话,即使app退出了MyPushPeceiver也能收到广播的,如果app被杀,pendingIntent不是带有上下文么,点击发出广播app也能收到重启吧?这一点还没有想通,或者方向想错了,或者个推不是这样实现的,或者跟里面的参数选项设置有关。有机会问问。
可以试着用透传消息,自己建立notification。然后点击通知栏的操作就可控了。用PendingIntentm。实践成功,解决了上述的个推demo现象2。
整体下来感觉个推反而比百度推送更简练,影响范围小,更容易花费较少的代码集成到自己的app。
发现:1.设置--正在运行,此处关闭是全部关闭 ,包括主程序和服务。
2.但手机长按menu等的最近程序清理,只会关闭后台程序,不会关掉service。
3.第三方的清理:介于两者之间吧,不同的手机自带的清理也不一样。跟Rom有关。极光推送整理了一些:第三方系统收不到推送的消息
4.按道理,应用不开启,只要有推送,通知栏就能收到信息的。pushservice会监听某些广播。
实测:1.各app的service会在被杀后重启:包括自己的core服务和推送。(有的是多个相互启动?大姨吗app三个服务没杀完第三个呢第一个被杀的又启动了,快速杀掉所有进程包括主进程和服务后通知栏的推送也消失了,全杀掉后很长时间未重启,微信同样,但全杀掉后能较快重启服务并能收到推送,蘑菇街,支付宝豌豆荚等等顽固app。一般通知service常驻。但这是htcD820t上的效果,这款手机设置中的正在运行的进程,列表查看时有时有误,正在运行的app有时不在列表上。
疑问:以前用的百度推送,没有这样的问题。也许是不同的app做的栈管理不同。两种推送实现的流程也不同。但是个推的常见问题和帮助文档没有提及这进程被杀的解答,百度推送倒有一些介绍:
应用关闭或结束进程后,还能收到推送吗?
应用退至后台或结束进程,百度云推送的Service会继续在后台运行并接收推送;部分情况下使用安全软件或内存管理工具强制清理后台,Service会被清除,但会快速重启;在小米和魅族手机上,用户清理后台应用后必须要等到再次打开app,开发者调用StartWork之后,Service才会在后台启动并继续接收推送。
极光推送等也有相应的解释,一般推送服务是常驻后台的,即便是app退出后。如果被杀会有自启动管理,如果没有自启动那要等到用户重启app,service再启动。另一方面,如果通知栏已经收到推送,此时服务被杀,要保证要么通知栏也被清除,要么不被清除时还能正常进入app。这点上面的实测中提到微信等的做法比较推荐,具体的操作还在学习。也就是通知栏收到消息后,杀掉与此app相关的所有进程服务后,通知栏上该条消息也被清除了。有的第三方清除工具会保证这一点。但是用手机自带设置中的停止程序关闭进程时,通知栏不一定能够清除,微信,大姨吗等app是关掉了,但我实测时发现自己的HiApp和WeApp此时并没有清除通知栏,但点击该通知后,HiApp点进去没反应,WeApp可以正常启动。区别是前者是个推,后者是百度推送,处理方式也不同,前者利用推送自己的notification,后者是收到消息后自己创建。目前还在调查:对HiApp的解决方法就是,要么清除进程后相关的通知栏都给清掉,要么不清掉保证点击后正常进去程序,个人感觉前者更简单,但是实现方式是靠对Notification定义的设置还是对程序的什么设置还没有搞清。要是改变Notification定义的设置,那也是第三方推送内置的,可能麻烦些。
参照:
3. Android 通知中心
4. Android实现点击通知栏后,先启动应用再打开目标Activity
解决:正在进行中。最好了解service的启动机制和生命周期。
1.程序正常退出和内存清理软件杀掉,都会运行BaseActivity的onDestroy,然后在管理栈中popup了HomeActivity,所以无法区分这两种就不能在onDestroy中清除所有该app的通知,正常退出后通知栏不应该消失。正常退出只能是两次点击back这种方式么?如果是,不是这种操作下的popup视为app被杀。
2.或者,即使app被杀,如果此时啊还有通知栏,Android实现点击通知栏后,可以启动应用再打开目标Activity。
3.参考以前自己的WeApp和上面的参照4,觉得自己创建notification比较灵活。
4.最终,使用个推demo现象2的解决方法,利用透传消息,自己创建通知,用pendingintent可以留住context信息。解决上述问题。只需要服务端改为传递透传消息。