访问Android NotificationListenerService设置

pow*_*984 10 notifications android android-4.3-jelly-bean

从4.3开始,Android有一个新的通知侦听器服务:http : //developer.android.com/about/versions/jelly-bean.html http://developer.android.com/reference/android/service/notification/NotificationListenerService. HTML

来自文档:

默认情况下禁用通知访问 - 应用程序可以使用新的Intent将用户直接带到Settings以在安装后启用侦听器服务.

我没有在任何地方看到发射的意图.仔细阅读"设置"文档似乎没有帮助:http: //developer.android.com/reference/android/provider/Settings.html

直接查看Settings类:https: //android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/provider/Settings.java

我看到ACTION_NOTIFICATION_LISTENER_SETTINGS已定义,但在使用Android Studio并指向4.3 ACTION_NOTIFICATION_LISTENER_SETTINGS时无法解析:

Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
Run Code Online (Sandbox Code Playgroud)

尝试更多手动似乎不起作用:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.android.settings", "android.settings.NOTIFICATION_LISTENER_SETTINGS");
Run Code Online (Sandbox Code Playgroud)

编辑:正如CommonsWare指出的那样正确地做到这一点:

Intent intent=new Intent("android.settings.NOTIFICATION_LISTENER_SETTINGS");
Run Code Online (Sandbox Code Playgroud)

导致崩溃:

(android.content.ActivityNotFoundException:找不到处理Intent的Activity {act = android.settings.NOTIFICATION_LISTENER_SETTINGS})

我错过了什么吗?我不确定如何将用户发送到正确的设置屏幕以在我的应用程序中启用此服务.

Com*_*are 17

我错过了什么吗?

好吧,在上一篇文章中,您将操作字符串与类名混淆."手动"方法是:

Intent intent=new Intent("android.settings.NOTIFICATION_LISTENER_SETTINGS");
Run Code Online (Sandbox Code Playgroud)

就Android Studio未找到的原因而言Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS,我不能说.


UPDATE

根据评论中的讨论,Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS目前不在Android SDK中(标有@hide).此外,"设置"应用的清单与操作字符串的版本略有不同:

Intent intent=new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
Run Code Online (Sandbox Code Playgroud)


and*_*per 8

这就是您今天可以使用它的方式,因为它将尝试为用户执行尽可能少的步骤来将其打开:

@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
fun getIntentForNotificationAccess(packageName: String, notificationAccessServiceClass: Class<out NotificationListenerService>): Intent =
        getIntentForNotificationAccess(packageName, notificationAccessServiceClass.name)


@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
fun getIntentForNotificationAccess(packageName: String, notificationAccessServiceClassName: String): Intent {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        return Intent(Settings.ACTION_NOTIFICATION_LISTENER_DETAIL_SETTINGS)
                .putExtra(Settings.EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME, ComponentName(packageName, notificationAccessServiceClassName).flattenToString())
    }
    val intent = Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
    val value = "$packageName/$notificationAccessServiceClassName"
    val key = ":settings:fragment_args_key"
    intent.putExtra(key, value)
    intent.putExtra(":settings:show_fragment_args", Bundle().also { it.putString(key, value) })
    return intent
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

startActivityForResult(getIntentForNotificationAccess(packageName, NotiService::class.java), REQUEST_CODE)
Run Code Online (Sandbox Code Playgroud)

或者:

startActivityForResult(getIntentForNotificationAccess(packageName, NotiService::class.java.name), REQUEST_CODE)
Run Code Online (Sandbox Code Playgroud)

请注意,遗憾的是,这对于其他各种情况是不可能的。甚至没有突出显示和焦点。针对这些情况,我提出了以下要求:


Gal*_*een 5

CommonsWare答案的附加内容是如何检查您是否具有该权限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {        
    if (!NotificationManagerCompat.getEnabledListenerPackages(this).contains(getPackageName())) {        //ask for permission
       Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
       startActivity(intent);
    }
}
Run Code Online (Sandbox Code Playgroud)