前言
在App开发中有时候需要知道app通知的系统设置是否开启,来进行相关的展示,与跳转系统设置的操作。
方案
在比较早的版本之前,系统没有相关的api进行直接的操作,需要通过反射的方式去进行操作。
但是现在已经不需要了,直接调用系统的api进行操作即可。
代码解决
- 判断是否开启状态,直接调用系统api,开启返回true,未开启返回false。
NotificationManagerCompat.from(this).areNotificationsEnabled();
- 跳转app详情页进行设置。
Uri packageURI = Uri.parse("package:" + this.getPackageName());
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
startActivity(intent);
源码分析
判断状态源码分三种情况
- api>= 24 则返回系统的判断,如下:
mNotificationManager.areNotificationsEnabled();
- api >=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;
}
- api <19 则返回true。
完整方法源码如下:
/**
* 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;
总结
关于app通知的系统设置就介绍到此,结束。