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

在Android8.0以上版本,通知Api发生了很大的变化,当targetSdk升级到26以上的时候,就会碰到不少问题,笔者从接手新项目,一直到今天才发现了一个隐藏很久的bug,点击通知栏,静态注册的广播代码不执行,经过写demo做实验,查阅资料,终于找到了问题所在,欢迎大家看看。

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

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

最近在重构聊天服务,有机会从新梳理下前人写的通知相关的逻辑,隐藏着一个很深的bug,遗留了应该有8个多月了。直到今天才定位出原因,之前一直怀疑是自己设备的问题????????,经过写demo,做实验验证,最终得出结论。

Android 8.0之后通知相关的Api又发生了很大的变化,接手项目的时候,没怎么关注过这块,一直以为没有问题,到今天测试验证,发现还是存在问题的????,问题表象是,点击App通知栏的通知消息,点击之后通知栏还在,一直没有反应(App业务中关于Click通知栏的逻辑没有生效)。抱着对代码怀疑的角度,自己创建了个demo工程,参考Notification的用法,自己做实验观察效果。

实验过程

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

首先创建了个demo工程,添加通知相关的代码,以及动态注册了一个BroadcastReceiver。private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

@Override    public void onReceive(Context context, Intent intent) {        if (intent == null || context == null) {            return;

}

mNotificationManager.cancel(NOTIFICATION_ID_LIVE);

String type = intent.getStringExtra(PUSH_TYPE);        if (PUSH_TYPE_LINK.equals(type)) {

mNumLinkes = 0;

} else if (PUSH_TYPE_LIVE.equals(type)) {

mNumLives = 0;

}        //这里可以重新计数    }

};private void registerHeadsetPlugReceiver() {

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(NOTIFICATION_CLICK_ACTION);

intentFilter.addAction(NOTIFICATION_DELETED_ACTION);

registerReceiver(mBroadcastReceiver, intentFilter);

}private void sendLiveNotification() {

Intent intent = new Intent(NOTIFICATION_CLICK_ACTION);    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);

channel.setBypassDnd(true);    //设置绕过免打扰模式

channel.canBypassDnd();       //检测是否绕过免打扰模式

channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);//设置在锁屏界面上显示这条通知

channel.setDescription("测试通知消息内容");

channel.setLightColor(Color.GREEN);

channel.setName("测试通知消息名称");

channel.setShowBadge(true);

channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});

channel.enableVibration(true);

mNotificationManager.createNotificationChannel(channel);

}

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);

String title = "Push测试";

mBuilder.setContentTitle(title);

mBuilder.setTicker(title);

mBuilder.setContentText("https://233.tv/over140");

mBuilder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));

mBuilder.setSmallIcon(R.mipmap.ic_launcher);

mBuilder.setDefaults(Notification.DEFAULT_ALL);

mBuilder.setWhen(System.currentTimeMillis());

mBuilder.setContentIntent(PendingIntent.getBroadcast(this, NOTIFICATION_ID_LIVE, intent, 0));

mBuilder.setDeleteIntent(PendingIntent.getBroadcast(this, NOTIFICATION_ID_LIVE, new Intent(NOTIFICATION_DELETED_ACTION).putExtra(PUSH_TYPE, PUSH_TYPE_LIVE), 0));

mNotificationManager.notify(NOTIFICATION_ID_LIVE, mBuilder.build());

}

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

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

android:enabled="true"

android:exported="false">

intent-filter>receiver>public class CustomBroadcastReceiver extends BroadcastReceiver {    private int NOTIFICATION_ID_LIVE = 101;    private String PUSH_TYPE_LIVE = "PUSH_TYPE_LIVE";    private String PUSH_TYPE = "push_type";    private String PUSH_TYPE_LINK = "PUSH_TYPE_LINK";    private int mNumLinkes;    private int mNumLives;

@Override    public void onReceive(Context context, Intent intent) {

NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);        if (intent == null || context == null) {            return;

}

mNotificationManager.cancel(NOTIFICATION_ID_LIVE);

String type = intent.getStringExtra(PUSH_TYPE);        if (PUSH_TYPE_LINK.equals(type)) {

mNumLinkes = 0;

} else if (PUSH_TYPE_LIVE.equals(type)) {

mNumLives = 0;

}

}

}

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

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

在查阅资料的过程也特意观察了下log输出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的代码逻辑,终于找到了问题所在,就这一行代码,花去了好几个小时????,但是值得的。

参考资料

Demo下载

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

发表于

2019-07-27 10:36 xing_star

阅读(1497)

评论(0) 编辑 收藏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值