使用NotificationListenerService检查对通知的访问

时间:2013-08-07 07:48:18

标签: android notifications

我正在使用> = 4.3 NotificationListenerService来访问通知。在第一次启动时,我的应用程序将用户带到“访问通知”系统面板,但是只要禁用“访问通知”中我的应用程序的复选框,我就会将用户带到那里。我在任何地方都没有找到isNotificationAccessEnabled() - 方法,但我肯定知道这是可能的,因为像Krome这样的应用也会这样做。

4 个答案:

答案 0 :(得分:52)

2016年6月15日编辑

我不确定添加了哪个版本的the support library,但现在内置了这个功能。只需使用:

NotificationManagerCompat.getEnabledListenerPackages(context);link to docs

这将返回Set<String>,您可以迭代以查找您的包名称。但请注意,我没有亲自测试过这个。但看起来可能更倾向于使用它代替我下面的旧解决方案。


旧解决方案

此代码适用于我的应用:

ContentResolver contentResolver = context.getContentResolver();
String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
String packageName = context.getPackageName();

// check to see if the enabledNotificationListeners String contains our package name
if (enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName))
{
    // in this situation we know that the user has not granted the app the Notification access permission
    throw new Exception();
}
else
{
    doSomethingThatRequiresNotificationAccessPermission();
}

我在enabledNotificationsListeners String看到的典型值如下所示:

  • 用户未提供任何应用通知访问权限
    • null""
  • 用户已授予一个应用通知访问权限
    • "com.woodblockwithoutco.remotecontrollerexample/com.woodblockwithoutco.remotecontrollerexample.RemoteControlService"
  • 用户已授予两个应用通知访问权限
    • "com.scootrnova.android/com.scootrnova.android.ListenerService:com.woodblockwithoutco.remotecontrollerexample/com.woodblockwithoutco.remotecontrollerexample.RemoteControlService"

这个实现非常简单,效果很好:)

P.S。我有想法使用来自this answer的硬编码“enabled_notification_listeners”字符串。

答案 1 :(得分:29)

我是Krome的开发者。我做了什么来检查是否启用了服务是添加公共静态变量,在onBind方法中变为true,在unbind中变为false。这就是这项服务的工作方式。

编辑:

public static boolean isNotificationAccessEnabled = false;

@Override
public void onListenerConnected() {
    isNotificationAccessEnabled = true;
}

@Override
public void onListenerDisconnected() {
    isNotificationAccessEnabled = false;
}

答案 2 :(得分:0)

使用稍作修改的@Damians答案即可很好地工作

template<typename U>
struct inherit : U { };

// looks broken
int test(inherit<int> arg);
// but that this point we dont really know yet what `inherit<int>` really is

// whoops inherit<int> is something different now   
template <> struct inherit<int> {};

// ... and now this is completely fine
int test(inherit<int> arg) {}

int main() {
    test( inherit<int>{} );
}

答案 3 :(得分:0)

从 Android 8.1 (SDK 27) 开始,您可以在 NotificationManager 上调用 isNotificationListenerAccessGranted。这是要使用的正确 API,而不是公认的答案之一。请参阅下面的说明。

像 shai tibber 也已经 said 接受的答案是不正确的。

即使没有授予 NotificationListener 访问权限,也可以调用

onListenerConnected()onListenerDisconnect()。所以依靠这个回调来设置一个布尔值会给出错误的结果。而 getEnabledListenerPackages(context‌​) 将只返回所有在 AndroidManifest (android:enabled=true) 中定义的已启用通知侦听器的包。它与用户访问没有直接关系。 documentation 明确指出:

获取其中包含已启用的通知侦听器组件的一组包。