androidandroid-manifestandroid-background

How to use NotificationListenerService in Android 14?


How I can be valid to use NotificationListenerService in Android 14? (API 34)
This application is going to be run on Android 14 or above only,
so it does not consider backward compatibility in order to run on older devices.

I want to make vibration more longer when a LINE (popular messaging app in Japan) message coming.

Note that unfortunately there is no preference to make vibration longer in the app.

To do above I want to observe an event then when LINE's notification has come, call vibration function.

But even modify AndroidManifest.xml, Nothing to happen when the app notification has come.

package com.example.notificationwatcher

import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log

class NotificationListener : NotificationListenerService() {
    override fun onNotificationPosted(sbn: StatusBarNotification?) {
        if (sbn != null) {
            Log.d("notification", sbn.packageName)
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.NotificationWatcher"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.NotificationWatcher">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".NotificationListener"
            android:label="NotificationListenerService"
            android:exported="true"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
            <meta-data
                android:name="android.service.notification.default_filter_types"
                android:value="conversations|alerting">
            </meta-data>
            <meta-data
                android:name="android.service.notification.disabled_filter_types"
                android:value="ongoing|silent">
            </meta-data>
        </service>
    </application>

</manifest>

Solution

  • It's not enough just to declare the service. A user of the app also must enable this permission manually.

    First of all, check if the permission is granted:

    private fun hasNotificationAccess(context: Context): Boolean {
        return Secure.getString(
            context.applicationContext.contentResolver,
            "enabled_notification_listeners"
        ).contains(context.applicationContext.packageName)
    }
    

    If not, open the settings screen:

    private fun openPermissions() {
        try {
            val settingsIntent =
                Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS")
            startActivity(settingsIntent)
        } catch (e: ActivityNotFoundException) {
            e.printStackTrace()
        }
    }
    

    After granting the permission your app should be able to intercept notifications.