【问题标题】:Check for access to notifications using NotificationListenerService使用 NotificationListenerService 检查对通知的访问
【发布时间】:2021-04-25 21:59:40
【问题描述】:

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

【问题讨论】:

    标签: android notifications


    【解决方案1】:

    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"

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

    附:我想到了使用来自this answer 的硬编码“enabled_notification_listeners”字符串。

    【讨论】:

    • 这对我很有效。我唯一需要改变的是 String packageName = context.getPackageName();到 String packageName = MyService.class.getName(); 因为我在我的启动器中检查它
    • 在我的测试设备 (LG G3) 上,字符串包含包名和监听器的类名。因此,如果您只有一个 NotificationListenerService,那么查找任一字符串都可以。 “Settings.Secure.getString”返回的字符串是一个冒号 (:) 分隔的类列表,格式如下:com.example.myapp/com.example.myapp.mynotificationlistener
    • 在现有的 Android 6 上,没有为任何应用启用通知侦听器,enabledNotificationListeners 确实变为 NULL。
    • 这是有效的,但不确定这是否是正确的方法,因为 enabled_notification_listeners 是隐藏的
    • NotificationManagerCompat.getEnabledListenerPackages(context) SO 上的最佳解决方案来检查它。感谢您更新答案。
    【解决方案2】:

    从 Android 8.1 (SDK 27) 开始,您可以在 NotificationManager 上调用 isNotificationListenerAccessGranted。这是要使用的正确 API。较旧的 Android 版本应使用 getEnabledListenerPackages 作为第二好的选择。依赖您的侦听器回调可能会产生不正确的结果。请参阅下面的explanation

    我是 Krome 的开发者。我为检查服务是否启用所做的工作是添加公共静态变量,该变量在 onBind 方法中更改为 true,在 unbind 中更改为 false。这就是这项服务的工作原理。

    编辑:

    public static boolean isNotificationAccessEnabled = false;
    
    @Override
    public void onListenerConnected() {
        isNotificationAccessEnabled = true;
    }
    
    @Override
    public void onListenerDisconnected() {
        isNotificationAccessEnabled = false;
    }
    

    【讨论】:

    • 嗨达米安,太棒了,非常感谢你的回答,我没想到会得到“这个人本人”的回复:-)!我会试试这个,如果你能自己解决,我会告诉你。
    • 仅供其他感兴趣的人使用,这是我的代码:public static boolean isNotificationAccessEnabled = false; @Override public IBinder onBind(Intent mIntent) { IBinder mIBinder = super.onBind(mIntent); isNotificationAccessEnabled = true; return mIBinder; } @Override public boolean onUnbind(Intent mIntent) { boolean mOnUnbind = super.onUnbind(mIntent); isNotificationAccessEnabled = false; return mOnUnbind; } 并在我的主要活动中检查 isNotificationAccessEnabled。
    • 此方案仅在您第一次检查时有效,因为系统只为 NotificationListenerService 调用一次 onBind 回调。如果您尝试取消选中(将调用 onUnbind)然后再次检查,则不会再次调用 onBind,因此 isNotificationAcessAnabled 将为 false。
    • 这不是一个可靠的解决方案。 Android 大部分时间都会调用 onBind/onUnbind,但根据 android 框架团队的设计,它并不是 100%:groups.google.com/forum/#!msg/android-developers/2IegSgtGxyE/…
    • 这仍然不是一个可靠的解决方案。在某些情况下,用户已授予对通知的访问权限,但不会调用 onListenerConnected() 方法。我在调试我自己的应用程序时多次遇到这种情况,该应用程序也使用 NotificationListenerService。让监听器连接并获得对通知的访问权限不是一回事。
    【解决方案3】:

    与稍作修改的@Damians 回答配合使用效果很好

    public class NotifyListener extends NotificationListenerService{    
            public static boolean listnerConnected = false;
        @Override
            public IBinder onBind(Intent intent) {
                Log.d(name,"onBind Called");
                listnerConnected = true;
                return super.onBind(intent);
        }   
    
            @Override
            public void onDestroy()
            {       
                super.onDestroy();        
                Log.e("destroy", "called");
                listnerConnected = false;
    
            }
    }
    

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-05
        • 2013-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-24
        • 1970-01-01
        相关资源
        最近更新 更多