如何在安卓系统中判断某个应用程序的通知是否已启用?

13

我有一个ListView,其中包含安装的应用程序列表,对于每个应用程序,我需要知道通知是否已启用。 目前,我使用以下代码来了解通知是否已启用:

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(mAppOps,value, appUID, appPackage) == AppOpsManager.MODE_ALLOWED);

我遇到了以下异常:

Caused by: java.lang.SecurityException: uid 10062 does not have android.permission.UPDATE_APP_OPS_STATS. W/System.err: at android.os.Parcel.readException(Parcel.java:1683) W/System.err: at android.os.Parcel.readException(Parcel.java:1636) W/System.err: at com.android.internal.app.IAppOpsService$Stub$Proxy.checkOperation(IAppOpsService.java:343)

我已经包含了

<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS"/>

我仍然遇到相同的错误。 使用哪些API可以获取该值,以确定它是否被阻止。

使用哪些API可以获取这些值?


1
你正在使用哪个API版本来构建应用程序,以及你正在测试应用程序的哪个Android版本?我之所以问这个问题是因为在Android 6及以上版本中,对于某些敏感权限,您需要在运行时从用户那里获取权限。https://developer.android.com/training/permissions/requesting.html - Shobhit Puri
看看 NotificationManager.getNotificationPolicy() 是否适合您。链接 - sonictt1
2个回答

9
我很抱歉,这只对当前应用程序可能是可能的。这就是NotificationManager的公共API为当前包提供areNotificationsEnabled()功能的原因。
在查看Android源代码时,我发现AppNotificationSettings——应用程序通知设置。第一个开关指示是否阻止通知。开关侦听器在这里,指向NotificationBackend。在这个类中,有一个方法: public boolean getNotificationsBanned(String pkg, int uid) 它使用了INotificationManager(编译期间从.aidl文件生成的类)及其方法: boolean areNotificationsEnabledForPackage(String pkg, int uid); 这是Android私有API,不能简单地调用。因此我尝试了反射:
try {
    NotificationManager mNotificationManager = null;
    Class<?> c = Class.forName("android.app.NotificationManager");
    Method method = c.getMethod("getService");
    Object obj = method.invoke(mNotificationManager);
    Class<?> clazz = Class.forName("android.app.INotificationManager$Stub$Proxy");
    Method areNotificationsEnabledForPackage = clazz.getMethod("areNotificationsEnabledForPackage", String.class, int.class);
    boolean blocked = (boolean) areNotificationsEnabledForPackage.invoke(obj, getPackageName(), android.os.Process.myUid());
    Log.d(MainActivity.class.getSimpleName(), String.valueOf(blocked));
} catch (Exception e) {
    e.printStackTrace();
}

然而,正如你所看到的,你必须先创建NotificationManager。遗憾的是,这个类是为包创建的。因此,上面的代码只能用于:

boolean blocked = (boolean) areNotificationsEnabledForPackage.invoke(obj, getPackageName(), android.os.Process.myUid());

然而,这并不起作用:
//InvocationTargetException will be thrown.
boolean blocked = (boolean) areNotificationsEnabledForPackage.invoke(obj, "com.android.camera", 10040);

结论:

无法完成。


我知道这很老,但是你可以使用final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(ServiceManager.getService(Context.NOTIFICATION_SERVICE));来获取实际运行的服务实例,而不是每个包重新创建一个实例。这样做是否允许您在没有ITE的情况下检查其他软件包? - Alex Newman

2

NotificationManagerCompat.areNotificationsEnabled() 可以获取当前应用程序的通知是否已启用。需要检查的是给定应用程序(具有 UID 和包名)是否已关闭通知(阻止所有通知)或未关闭。 - Abc.Xyz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接