关于消息推送和service的一些调查-清理内存通知栏点击无响应

起因:做了两个带推送的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定义的设置,那也是第三方推送内置的,可能麻烦些。

  

参照:

1. 如何让android的service一直在后台运行?

2. Android 中的 Service 全面总结

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信息。解决上述问题。只需要服务端改为传递透传消息。

原文地址:https://www.cnblogs.com/permanent2012moira/p/4768781.html