前不久由於API26(Android 8.0)以上的設備沒法顯示通知欄,因此網上查閱了比較多了資料,得出結論,API26之後引入了通知渠道這麼個東西,而後就寫了一篇問題對應的博文:Android 8.0通知欄(Notification)適配,在模擬上是完美運行,但是當我前兩天安裝到真機上測試時,咦?怎麼又無效了?而後我就想着,是否是通知權限沒打開?由於模擬器上不少權限的控制和真機上差異很大,我打開設置一看,還真是!那麼本文就接着Android 8.0通知欄(Notification)適配做一個補充。java
文章目錄
Android 10 真機測試效果:
判斷通知權限是否打開
一行代碼判斷
咱們要打開通知 管理頁面 第一步固然是判斷 通知權限是否打開了? ,打開了咱們就不須要跳轉到通知管理頁面了,沒打開咱們才進行跳轉。android
這裏咱們用NotificationManagerCompat提供的 .areNotificationsEnabled() 方法來判斷通知權限是否打開,返回的是boolean值app
NotificationManagerCompat.from(this).areNotificationsEnabled()
注意:這個方法只適用於API19(Android 4.4)以上,API19如下會直接返回true,固然咱們不是特殊開發也能夠忽略了,畢竟如今市場上低於 Android4.4 的手機恐怕很差找,並且貌似Android4.4如下的對權限這塊也沒有太嚴格~測試
areNotificationsEnabled() 的源碼(可忽略)
咱們來看看 areNotificationsEnabled() 的源碼,源碼能夠很清晰明朗地看到,API24以上直接調用 mNotificationManager.areNotificationsEnabled();
方法,而 API19 -API 23 則是經過反射的方式來獲取,API 19 如下就直接返回 true 了ui
/** * Returns whether notifications from the calling package are not blocked. */ public boolean areNotificationsEnabled() { if (Build.VERSION.SDK_INT >= 24) { return mNotificationManager.areNotificationsEnabled(); } else if (Build.VERSION.SDK_INT >= 19) { AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); ApplicationInfo appInfo = mContext.getApplicationInfo(); String pkg = mContext.getApplicationContext().getPackageName(); int uid = appInfo.uid; try { Class<?> appOpsClass = Class.forName(AppOpsManager.class.getName()); Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class); Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION); int value = (int) opPostNotificationValue.get(Integer.class); return ((int) checkOpNoThrowMethod.invoke(appOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED); } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | InvocationTargetException | IllegalAccessException | RuntimeException e) { return true; } } else { return true; } }
跳轉到通知管理頁面
通知權限判斷完了固然是要根據判斷結果來進行跳轉了,上面咱們能夠知道 NotificationManagerCompat.from(this).areNotificationsEnabled()
是會返回 boolean 值的,true 表明權限已經打開,反之則沒有打開,這裏咱們能夠寫一個 if 語句根據返回結果來進行判斷,這裏直接給一個現成的方法吧this
方法邏輯:
- 首先判斷 通知權限是否打開
- 若是判斷結果是:false(權限沒打開),再進行當前手機的 API 判斷
- 經過判斷API,來調用不一樣的方法,實現跳轉到應用通知設置的頁面
private boolean intent(Context context) {//判斷應用的通知權限是否打開,返回Boolean值 if (!NotificationManagerCompat.from(context).areNotificationsEnabled()) { Intent localIntent = new Intent(); //判斷API,跳轉到應用通知管理頁面 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0及以上 localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); localIntent.setData(Uri.fromParts("package", context.getPackageName(), null)); } else (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//8.0如下 localIntent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); localIntent.putExtra("app_package", context.getPackageName()); localIntent.putExtra("app_uid", context.getApplicationInfo().uid); } context.startActivity(localIntent); return false; } return true; }
補充
這裏補充一下 Android 8.0 +的 Notification通知欄消息 的使用,相對於之前也只是加了一個NotificationChannel通知渠道,想要詳細看的能夠去我前一篇關於通知欄的博客:Android 8.0通知欄(Notification)適配spa
方法邏輯
- 首先經過上面的 通知權限判斷 方法判斷通知權限是否打開
- 打開了的話判斷當前手機的API,若是是在 26 (Android 8.0)以上則多實例化一個NotificationChannel對象,並傳入一個 ID(用戶不可見,要保證id的惟一性) 和一個 Name(用戶能看到) ,最後是一個通知的優先級,這裏我設置的 高(IMPORTANCE_HIGH)
- 若是API 在 26 如下,咱們則直接調用之前使用的方法便可,這樣就能夠兼容上下API了
public void show(Context context, String title, String msg) { if (intent(context)) { NotificationManager manager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); Notification notification = null; if (Build.VERSION.SDK_INT >= 26) {//API26以上的方法 NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); manager.createNotificationChannel(channel); notification = new Notification.Builder(context, "id") .setContentTitle(title) .setContentText(msg) .setSmallIcon(R.mipmap.img_icon) .build(); } else {//API26如下 notification = new Notification.Builder(context) .setContentTitle(title) .setContentText(msg) .setSmallIcon(R.mipmap.img_icon) .build(); } manager.notify(1, notification); } }
若是文章對你還算有點幫助,點個贊吧!.net