如何知道android中的应用程序是不是启用了通知?

Posted

技术标签:

【中文标题】如何知道android中的应用程序是不是启用了通知?【英文标题】:How to know whether Notifications are enabled or not for an application in android?如何知道android中的应用程序是否启用了通知? 【发布时间】:2017-02-11 11:07:29 【问题描述】:

我有一个 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);

我遇到了以下异常:

原因:java.lang.SecurityException: uid 10062 没有 android.permission.UPDATE_APP_OPS_STATS。 W/System.err:在 android.os.Parcel.readException(Parcel.java:1683) W/System.err:在 android.os.Parcel.readException(Parcel.java:1636) W/System.err:在 com.android.internal.app.IAppOpsService$Stub$Proxy.checkOperation(IAppOpsService.java:343)

我已经加入了

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

我仍然遇到同样的错误。 使用什么api可以获取是否被阻止的值

【问题讨论】:

您使用哪个 API 版本来构建应用程序以及您在哪个 android 版本上测试您的应用程序?我问这个是因为对于 Android 6 及更高版本中的某些敏感权限,您需要在运行时获得用户的权限。 developer.android.com/training/permissions/requesting.html 看看NotificationManager.getNotificationPolicy() 是否为您服务。 Link 【参考方案1】:

恐怕这仅适用于当前应用程序。这就是为什么 NotificationManager 的公共 API 具有用于当前包的函数 areNotificationsEnabled()

在查看 android 源代码时,我发现 AppNotificationSettings - 应用程序通知设置。第一个开关指示通知是否被阻止。切换监听器是here,它指向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 的情况下检查其他包?【参考方案2】:

看看能不能用 NotificationManagerCompat.areNotificationsEnabled() https://developer.android.com/reference/android/support/v4/app/NotificationManagerCompat.html#areNotificationsEnabled()

Android 4.1: How to check notifications are disabled for the application?

【讨论】:

NotificationManagerCompat.areNotificationsEnabled() 给出是否为正在运行的应用程序启用通知。需要检查给定应用程序(带有 UID 和包名称)是否关闭了通知(全部阻止)

以上是关于如何知道android中的应用程序是不是启用了通知?的主要内容,如果未能解决你的问题,请参考以下文章

如何知道应用程序是不是从 android 通知托盘打开?

如何检查 iPhone 上是不是启用了通知

如何在xamarin android中启用浮动通知和锁屏通知(Java或Kotlin都可以)

我如何检查用户是不是真的在他的手机上启用了 android 中的 gps 位置

如何启用和禁用解析推送通知 Android

默认情况下在我的 android 应用中启用所有通知设置