11

Android has a new notification listener service as of 4.3: http://developer.android.com/about/versions/jelly-bean.html http://developer.android.com/reference/android/service/notification/NotificationListenerService.html

From the docs:

Notification access is disabled by default — apps can use a new Intent to take the user directly to the Settings to enable the listener service after installation.

I don't see the intent to fire documented anywhere. Perusing the Settings doc doesn't seem helpful: http://developer.android.com/reference/android/provider/Settings.html

Looking at the Settings class directly: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/provider/Settings.java

I see ACTION_NOTIFICATION_LISTENER_SETTINGS defined, but when using Android Studio and pointing at 4.3 ACTION_NOTIFICATION_LISTENER_SETTINGS can't be resolved:

Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);

Trying it more manually doesn't seem to work:

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

edit: doing it the correct way as CommonsWare pointed out below:

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

leads to a crash:

(android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.NOTIFICATION_LISTENER_SETTINGS })

Am I missing something? I'm not sure how to send the user to the proper settings screen to enable this service in my app.

powerj1984
  • 2,146
  • 1
  • 21
  • 34
  • interesting question. Is it possible with the new API to get the notification text and the discription and so on? – Cilenco Jul 27 '13 at 18:57
  • Yep, once the service is setup you can grab notifications directly (http://developer.android.com/reference/android/app/Notification.html) – powerj1984 Jul 27 '13 at 19:15
  • Okay great! But there are no mathods to get the notification or discription text from a `StatusBarNotification` – Cilenco Jul 27 '13 at 19:25
  • http://developer.android.com/reference/android/service/notification/StatusBarNotification.html has a getNotification() method – powerj1984 Jul 27 '13 at 23:08
  • Yes but from there you have to work with the `Parcel` and that is not so easy to get all the different text messages from the notification – Cilenco Jul 28 '13 at 07:12
  • Have you managed to get the notificationlistenerservice class to work in your app?http://stackoverflow.com/questions/17911883/cannot-get-the-notificationlistenerservice-class-to-work/17916173 – CeejeeB Jul 29 '13 at 19:50
  • @Cilenco i think you are using sdk < 18.. that's way you can't see StatusBarNotification – AJit Sep 09 '13 at 12:29

3 Answers3

17

Am I missing something?

Well, in your last one, you are conflating an action string with a class name. The "manual" approach would be:

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

In terms of why Android Studio is not finding Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS, that I can't say.


UPDATE

Based on the discussion in the comments, Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS is not in the Android SDK at present (marked with @hide). Also, the manifest for the Settings app has a slightly different version of the action string:

Intent intent=new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
  • Turns out ACTION_NOTIFICATION_LISTENER_SETTINGS has @hide in its documentation, which I'm guessing shouldn't be there - though I thought it would just hide the documentation, not make it impossible to resolve within Android Studio. Unfortunately trying it the way mentioned in your answer ends up with a crash: Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.NOTIFICATION_LISTENER_SETTINGS – powerj1984 Jul 25 '13 at 15:24
  • 1
    @powerj1984: "Turns out ACTION_NOTIFICATION_LISTENER_SETTINGS has @hide in its documentation" -- I don't see that in the source you linked to. "though I thought it would just hide the documentation" -- no, `@hide` removes the item from the SDK entirely. Regarding the `ActivityNotFoundException`, what are you testing on? – CommonsWare Jul 25 '13 at 15:37
  • Line number 667 in the linked source doesn't have @hide? Weird, it does on my end. Testing on a Nexus 4 with 4.3 – powerj1984 Jul 25 '13 at 15:38
  • @powerj1984: Ah, I see. That `@hide` is in the comment. Usually, I see it outside of any JavaDoc comments, which is why I glossed over it. The fact that it's not showing up in the JavaDocs, though, means it must still be honored. My apologies for missing it. It's odd that it's not working, though, as I see that action in the manifest for Settings in the source code: https://github.com/android/platform_packages_apps_settings/blob/jb-mr2-release/AndroidManifest.xml – CommonsWare Jul 25 '13 at 15:48
  • No worries at all about missing it - I thought maybe I linked the wrong source initially. I guess I'll check the bug tracker on this. It does seem bizarre that it isn't working using the string directly. – powerj1984 Jul 25 '13 at 15:49
  • 1
    Oh, oops! I left the 'ACTION_' bit off the beginning of the string. Using that allows me to use the string directly. – powerj1984 Jul 25 '13 at 16:00
  • 1
    @powerj1984: Now that is interesting. Usually, the string representation of the action does not have `ACTION_` in it, which fits what the `@hide` entry in `Settings` has. However, the *manifest entry* has `ACTION_` in it, so you need to have that in the action in the `Intent` as well. It will be interesting to see how they reconcile all of this later on. In the meantime, I will update the answer. – CommonsWare Jul 25 '13 at 16:03
  • 1
    FYI I took the information gathered here and reported the bug on the issue tracker: https://code.google.com/p/android/issues/detail?id=58030&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars – powerj1984 Jul 29 '13 at 13:57
7

Additional to CommonsWare answer here is how to check if you have that permission

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);
    }
}
Galeen
  • 139
  • 1
  • 7
3

This is how you can use it today, as it will try to go to as few steps for the user as possible, to turn it on:

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

Example usage:

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

or:

startActivityForResult(getIntentForNotificationAccess(packageName, NotiService::class.java.name), REQUEST_CODE)
android developer
  • 106,412
  • 122
  • 641
  • 1,128
  • These **magic** keys are from [here](https://android.googlesource.com/platform/packages/apps/Settings/+/master/src/com/android/settings/SettingsActivity.java#101) – Vlad Sep 25 '20 at 09:21
  • @Vlad Thank you. How did you find it? I can't reach this file. Do you know perhaps of a way to use these for system-alert-window permission too, for Android 11 ? – android developer Sep 25 '20 at 11:31
  • These args has any effect only for Android 9 (my app will be simply highlighted in list). I have tested with multiple versions – Vlad Sep 25 '20 at 13:34
  • @Vlad Too bad. Do you know which types of special permissions do handle this "magic"? – android developer Sep 25 '20 at 15:26