Android 8.0+通知栏(Notification)适配详解,判断通知权限是否打开,并跳转至通知管理页面

前不久由于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

在这里插入图片描述

相关文章
相关标签/搜索