经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
对Android 8.0以上版本通知点击无效的一次分析
来源:cnblogs  作者:xing_star  时间:2019/7/29 8:51:11  对本文有异议

版权声明:本文为xing_star原创文章,转载请注明出处!

本文同步自http://javaexception.com/archives/178

对Android 8.0以上版本通知点击无效的一次分析

最近在重构聊天服务,有机会从新梳理下前人写的通知相关的逻辑,隐藏着一个很深的bug,遗留了应该有8个多月了。直到今天才定位出原因,之前一直怀疑是自己设备的问题????,经过写demo,做实验验证,最终得出结论。
Android 8.0之后通知相关的Api又发生了很大的变化,接手项目的时候,没怎么关注过这块,一直以为没有问题,到今天测试验证,发现还是存在问题的??,问题表象是,点击App通知栏的通知消息,点击之后通知栏还在,一直没有反应(App业务中关于Click通知栏的逻辑没有生效)。抱着对代码怀疑的角度,自己创建了个demo工程,参考Notification的用法,自己做实验观察效果。

实验过程

这里在回顾下自己做实验的过程。

首先创建了个demo工程,添加通知相关的代码,以及动态注册了一个BroadcastReceiver。

  1. private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. if (intent == null || context == null) {
  5. return;
  6. }
  7. mNotificationManager.cancel(NOTIFICATION_ID_LIVE);
  8. String type = intent.getStringExtra(PUSH_TYPE);
  9. if (PUSH_TYPE_LINK.equals(type)) {
  10. mNumLinkes = 0;
  11. } else if (PUSH_TYPE_LIVE.equals(type)) {
  12. mNumLives = 0;
  13. }
  14. //这里可以重新计数
  15. }
  16. };
  1. private void registerHeadsetPlugReceiver() {
  2. IntentFilter intentFilter = new IntentFilter();
  3. intentFilter.addAction(NOTIFICATION_CLICK_ACTION);
  4. intentFilter.addAction(NOTIFICATION_DELETED_ACTION);
  5. registerReceiver(mBroadcastReceiver, intentFilter);
  6. }
  1. private void sendLiveNotification() {
  2. Intent intent = new Intent(NOTIFICATION_CLICK_ACTION);
  3. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  4. NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
  5. channel.setBypassDnd(true); //设置绕过免打扰模式
  6. channel.canBypassDnd(); //检测是否绕过免打扰模式
  7. channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);//设置在锁屏界面上显示这条通知
  8. channel.setDescription("测试通知消息内容");
  9. channel.setLightColor(Color.GREEN);
  10. channel.setName("测试通知消息名称");
  11. channel.setShowBadge(true);
  12. channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
  13. channel.enableVibration(true);
  14. mNotificationManager.createNotificationChannel(channel);
  15. }
  16. NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
  17. String title = "Push测试";
  18. mBuilder.setContentTitle(title);
  19. mBuilder.setTicker(title);
  20. mBuilder.setContentText("https://233.tv/over140");
  21. mBuilder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
  22. mBuilder.setSmallIcon(R.mipmap.ic_launcher);
  23. mBuilder.setDefaults(Notification.DEFAULT_ALL);
  24. mBuilder.setWhen(System.currentTimeMillis());
  25. mBuilder.setContentIntent(PendingIntent.getBroadcast(this, NOTIFICATION_ID_LIVE, intent, 0));
  26. mBuilder.setDeleteIntent(PendingIntent.getBroadcast(this, NOTIFICATION_ID_LIVE, new Intent(NOTIFICATION_DELETED_ACTION).putExtra(PUSH_TYPE, PUSH_TYPE_LIVE), 0));
  27. mNotificationManager.notify(NOTIFICATION_ID_LIVE, mBuilder.build());
  28. }

第一步的测试代码比较简单,在MainActivity调用sendLiveNotification()方法,就会出现通知栏,之后呢,点击通知栏会发送广播,我们在MainActivity注册了这个广播事件,就能够接收到,看起来没问题。到这里把怀疑点放到了静态注册上,BroadcastReceiver在AndroidManifest.xml中的注册。

接着就是修改代码,把动态注册的代码调整为一个CustomBroadcastReceiver,然后在AndroidManifest.xml中进行注册

  1. <receiver
  2. android:name=".CustomBroadcastReceiver"
  3. android:enabled="true"
  4. android:exported="false">
  5. <intent-filter>
  6. <action android:name="me.star.notificationdemo2.click" />
  7. <action android:name="me.star.notificationdemo2.delete" />
  8. </intent-filter>
  9. </receiver>
  1. public class CustomBroadcastReceiver extends BroadcastReceiver {
  2. private int NOTIFICATION_ID_LIVE = 101;
  3. private String PUSH_TYPE_LIVE = "PUSH_TYPE_LIVE";
  4. private String PUSH_TYPE = "push_type";
  5. private String PUSH_TYPE_LINK = "PUSH_TYPE_LINK";
  6. private int mNumLinkes;
  7. private int mNumLives;
  8. @Override
  9. public void onReceive(Context context, Intent intent) {
  10. NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
  11. if (intent == null || context == null) {
  12. return;
  13. }
  14. mNotificationManager.cancel(NOTIFICATION_ID_LIVE);
  15. String type = intent.getStringExtra(PUSH_TYPE);
  16. if (PUSH_TYPE_LINK.equals(type)) {
  17. mNumLinkes = 0;
  18. } else if (PUSH_TYPE_LIVE.equals(type)) {
  19. mNumLives = 0;
  20. }
  21. }
  22. }

调整完后,继续验证自己的想法。

运行程序,开启debug模式,发现点击通知栏后,在CustomBroadcastReceiver中没有拦截到,到这里就确定了问题肯定是出现在静态注册上面,但是之前的项目中,有些第三方的broadcastReceiver是静态注册,但最终是执行了onReceiver的方法,那肯定是我的使用姿势有问题。于是google搜索了一番,关键词就是android broadcastreceiver androidmanifest android 8.0 不运行,第一篇文章就是我想要找的。参考了一番,发现提到的几个说法值得一试,目前只验证了

  1. intent.setPackage(getPackageName());

在查阅资料的过程也特意观察了下log输出

  1. 07-26 23:30:14.452 1637-1688/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=me.star.notificationdemo2.click flg=0x10 } to notification.star.me.notificationdemo2/.CustomBroadcastReceiver

说的是后台执行不被允许?反正搞不懂啥情况,没仔细看相关的源码。加上intent.setPackage(getPackageName());后重新编译

之后重新debug,发现这次执行了onReceiver的代码逻辑,终于找到了问题所在,就这一行代码,花去了好几个小时??,但是值得的。

 

参考资料

https://blog.csdn.net/u011386173/article/details/82889275

Demo下载

链接:https://pan.baidu.com/s/1Ac97_0kFxKavpQi6-YxB2w 密码:niun  (demo中包含Git版本控制,可以通过切换commit,查阅动态注册,静态注册的代码)

 

原文链接:http://www.cnblogs.com/xing-star/p/11254118.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号