Question

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.

Was it helpful?

Solution

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

OTHER TIPS

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

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)

Note that sadly this isn't possible for various other cases, sadly. Not even highlight&focus. For these cases, I've made these requests:

Thanks @android developer for great answer, but I have a little clarification.

You MUST call startActivity inside try/catch because some OS (Honor/Huawei on Android 11) doesn't have "Settings.ACTION_NOTIFICATION_LISTENER_DETAIL_SETTINGS", so this exception is thrown:

No Activity found to handle Intent { act=android.settings.NOTIFICATION_LISTENER_DETAIL_SETTINGS (has extras) }

Use in this way:

try {
    startActivity(getIntentForNotificationAccess(packageName, NotiService::class.java))
} catch (e: Exception) {
    if (Build.VERSION.SDK_INT >= 22) {
        try {
            startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS))
        } catch (e1: Exception) {
            e1.printStackTrace()
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top