版權聲明:本文為xing_star原創文章,轉載請注明出處!
本文同步自http://javaexception.com/archives/178
對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中進行注冊
<receiver android:name=".CustomBroadcastReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="me.star.notificationdemo2.click" /> <action android:name="me.star.notificationdemo2.delete" /> </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的代碼邏輯,終於找到了問題所在,就這一行代碼,花去了好幾個小時😂,但是值得的。
參考資料
https://blog.csdn.net/u011386173/article/details/82889275
Demo下載
鏈接:https://pan.baidu.com/s/1Ac97_0kFxKavpQi6-YxB2w 密碼:niun (demo中包含Git版本控制,可以通過切換commit,查閱動態注冊,靜態注冊的代碼)
