【问题标题】:Accessing Android NotificationListenerService Settings访问 Android NotificationListenerService 设置
【发布时间】:2013-07-25 13:55:01
【问题描述】:

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

来自文档:

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

我看不到任何地方都记录了开枪的意图。仔细阅读设置文档似乎没有帮助: 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);

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

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.android.settings", "android.settings.NOTIFICATION_LISTENER_SETTINGS");

编辑:按照 CommonsWare 在下面指出的正确方式进行操作:

Intent intent=new Intent("android.settings.NOTIFICATION_LISTENER_SETTINGS");

导致崩溃:

(android.content.ActivityNotFoundException: No Activity found to 处理意图 { act=android.settings.NOTIFICATION_LISTENER_SETTINGS })

我错过了什么吗?我不确定如何将用户引导至正确的设置屏幕以在我的应用中启用此服务。

【问题讨论】:

标签: android notifications android-4.3-jelly-bean


【解决方案1】:

我错过了什么吗?

好吧,在您的最后一个中,您将操作字符串与类名混为一谈。 “手动”方法是:

Intent intent=new Intent("android.settings.NOTIFICATION_LISTENER_SETTINGS");

关于为什么 Android Studio 没有找到 Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS,我不能说。


更新

根据cmets中的讨论,Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS目前不在Android SDK中(标记为@hide)。此外,设置应用程序的清单具有稍微不同的操作字符串版本:

Intent intent=new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");

【讨论】:

  • 原来 ACTION_NOTIFICATION_LISTENER_SETTINGS 在其文档中有@hide,我猜它不应该在那里 - 尽管我认为它只会隐藏文档,而不是让它无法在 Android Studio 中解决。不幸的是,以您的答案中提到的方式尝试它最终导致崩溃: 原因:android.content.ActivityNotFoundException:未找到处理 Intent { act=android.settings.NOTIFICATION_LISTENER_SETTINGS 的活动
  • @powerj1984:“原来 ACTION_NOTIFICATION_LISTENER_SETTINGS 在其文档中有@hide”——我在您链接到的源代码中没有看到。 “虽然我认为它只会隐藏文档”——不,@hide 完全从 SDK 中删除了该项目。关于ActivityNotFoundException,你在测试什么?
  • 哦,哎呀!我在字符串的开头留下了“ACTION_”位。使用它可以让我直接使用字符串。
  • @powerj1984:这很有趣。通常,操作的字符串表示中没有ACTION_,这与Settings 中的@hide 条目相匹配。但是,manifest entry 中包含 ACTION_,因此您还需要在 Intent 的操作中包含它。看看他们稍后如何调和所有这些将会很有趣。同时,我会更新答案。
  • 仅供参考,我收集了此处收集的信息并报告了问题跟踪器上的错误:code.google.com/p/android/issues/…
【解决方案2】:

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);
    }
}

【讨论】:

  • 您不必检查集合中的每一项来检查其中一项是否等于当前一项。最好只使用contains。代码也更短。
  • 这是正确的@androiddeveloper,我也更改了示例。
  • 如果包已启用,您是在询问权限,但您只需要在未启用时询问!
  • @Andris 这是真的,已更改
【解决方案3】:

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

@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
}

示例用法:

startActivityForResult(getIntentForNotificationAccess(packageName, NotiService::class.java), REQUEST_CODE)

或:

startActivityForResult(getIntentForNotificationAccess(packageName, NotiService::class.java.name), REQUEST_CODE)

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

【讨论】:

  • 这些魔法键来自here
  • @Vlad 谢谢。你是怎样找到它的?我无法访问此文件。对于 Android 11,您是否也知道将这些用于系统警报窗口权限的方法?
  • 这些参数仅对 Android 9 有效(我的应用将在列表中简单突出显示)。我已经测试了多个版本
  • @Vlad 太糟糕了。你知道哪些类型的特殊权限可以处理这种“魔法”吗?
猜你喜欢
  • 2015-05-24
  • 2021-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多