低于Android O的设备如何编程检测气泡或浮动通知是否开启
Android 8.0(O)以下设备通知权限检测方案
核心实现逻辑
Android 8.0以下版本没有公开的通知权限查询API,也不存在通知渠道的概念,我们可以通过反射调用系统隐藏的AppOpsManager接口,校验通知发送权限的状态,适用版本区间为Android 4.4 ~ Android 7.1。
public boolean isNotificationEnabled(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // O及以上可走你已有的通知渠道检测逻辑 NotificationManager manager = context.getSystemService(NotificationManager.class); return manager.areNotificationsEnabled(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 4.4到7.1版本走AppOps反射校验 AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); ApplicationInfo appInfo = context.getApplicationInfo(); String pkg = context.getApplicationContext().getPackageName(); int uid = appInfo.uid; try { Class<?> appOpsClass = Class.forName(AppOpsManager.class.getName()); Method checkOpNoThrowMethod = appOpsClass.getMethod("checkOpNoThrow", 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 (Exception e) { // 反射调用失败走降级逻辑,默认返回true,避免误判 return true; } } else { // 4.4以下没有系统级通知开关,默认支持发送通知 return true; } }
适配注意事项
- 部分国产定制ROM(小米、华为、魅族等)对通知权限做了独立管控,通用反射方案存在少量误判,无需极致兼容的场景下可直接使用,需高准确率的可以针对对应ROM做单独适配
- 反射调用失败时直接返回
true做降级处理,避免ROM接口篡改导致的业务异常 - 权限被关闭时如需跳转系统设置页开启,低版本通用跳转代码如下,跳转失败可降级跳转到应用详情页:
Intent intent = new Intent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); intent.putExtra("app_package", context.getPackageName()); intent.putExtra("app_uid", context.getApplicationInfo().uid); } else { intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", context.getPackageName(), null)); } context.startActivity(intent);
内容的提问来源于stack exchange,提问作者ProJin
相关产品推荐
相关产品推荐

