Plugin for reading all android notifications in capacitor. With this plugin you can read other apps notifications and create some automations based on their contents.
It is a replacement of https://github.com/Alone2/capacitor-notificationlistener, that was archived due to lack of updates.
This plugin works on Android 15 and adds few additional features like persistent notifications caching. Tested on Capacitor v6.
Note: Plugin is in active development, bugs are to be expected, especially in background processing service.
Since version 0.4 background service is more robust and should withstand reboots and app kills, but I've tested it only on few devices with Android 15 to 12.
npm install capacitor-notifications-listener
npx cap sync
Next click Android studio -> Sync project with gradle files.
To enable the listener, add this service to your AndroidManifest.xml
inside <application>
:
<service android:name="com.capacitor.notifications.listener.NotificationService"
android:exported="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Import the plugin.
import { AndroidNotification, NotificationsListener, NotificationsListenerPlugin } from 'capacitor-notifications-listener';
const systemNotificationListener: NotificationsListenerPlugin = NotificationsListener;
Start listening for notifications.
systemNotificationListener.startListening();
Add a listener for new notifications or the removal of notifications.
Make sure you have called sn.startListening()
to be able to receive notifications.
systemNotificationListener.addListener("notificationReceivedEvent", (notification: AndroidNotification) => {
// logic ...
});
systemNotificationListener.addListener("notificationRemovedEvent", (notification: AndroidNotification) => {
// logic ...
});
AndroidNotification Interface. The anotomy of android notifications is explained here.
interface AndroidNotification {
apptitle: string; // Title of a notifications' app
text: string; // Text of a notification
textlines: string[]; // Text of a multi-line notification
title: string; // Title of a notification
time: number; // Received timestamp
package: string; // Package-name of a notifications' app
}
Check if the App is listening for notifications.
If it is not, even though systemNotificationListener.startListening()
was called,
your app doesn't have sufficient permissions to observe notifications.
Call systemNotificationListener.requestPermission()
to "open settings -> apps -> special app access -> notification read, reply and control" screen. User must select your app and enable this special permission manually, so make sure to instruct the user how to do it.
systemNotificationListener.isListening().then((isListening : boolean) => {
if (!isListening.value)
// show permission screen
systemNotificationListener.requestPermission()
});
Open settings so that the user can authorize your app.
systemNotificationListener.requestPermission();
To listen only to specific apps, provide array of packages names in startListening
options object:
systemNotificationListener.startListening({ packagesWhitelist: ['com.example.appone', 'org.example.apptwo'] });
To replace the whitelist with the new one after initialization, use replacePackagesWhitelist()
method.
The service will continue to receive notifications even if your WebView app was killed. If you enable caching, those notifications will be saved in Android Preferences Storage as JSON. It's not the quickest way to store data, but if your app does not process thousands of notifications, it won't be a problem. Better storage solution is in TODO.
To enable caching, pass additional options when starting:
systemNotificationListener.startListening({ cacheNotifications: true });
Next, when your aplication resumes or starts, call this method and the plugin will send any saved notifications. Notifications will be passed the same way as the new ones are passed to your app, so you don't have to do anything else besides calling that method. After calling, cache will be cleared.
systemNotificationListener.restoreCachedNotifications();
addListener('notificationRemovedEvent', ...)
addListener('notificationReceivedEvent', ...)
startListening(...)
restoreCachedNotifications()
stopListening()
requestPermission()
isListening()
removeAllListeners()
replacePackagesWhitelist(...)
- Interfaces
addListener(eventName: 'notificationRemovedEvent', listenerFunc: (info: AndroidNotification) => void) => Promise<PluginListenerHandle>
Param | Type |
---|---|
eventName |
'notificationRemovedEvent' |
listenerFunc |
(info: AndroidNotification) => void |
Returns: Promise<PluginListenerHandle>
addListener(eventName: 'notificationReceivedEvent', listenerFunc: (info: AndroidNotification) => void) => Promise<PluginListenerHandle>
Param | Type |
---|---|
eventName |
'notificationReceivedEvent' |
listenerFunc |
(info: AndroidNotification) => void |
Returns: Promise<PluginListenerHandle>
startListening(options: ListenerOptions) => Promise<void>
Param | Type |
---|---|
options |
ListenerOptions |
restoreCachedNotifications() => Promise<void>
Call this after attaching listeners and after starting listening. If nothing is cached, nothing will happen.
stopListening() => Promise<void>
requestPermission() => Promise<void>
Navigates to special app permissions settings screen.
isListening() => Promise<{ value: boolean; }>
Returns: Promise<{ value: boolean; }>
removeAllListeners() => Promise<void>
replacePackagesWhitelist(options: { packagesWhitelist: string[] | null; }) => Promise<void>
Replace the current white list of packages with new one. send null to disable whitelist.
Param | Type |
---|---|
options |
{ packagesWhitelist: string[] | null; } |
Prop | Type |
---|---|
remove |
() => Promise<void> |
Prop | Type |
---|---|
apptitle |
string |
text |
string |
textlines |
string[] |
title |
string |
time |
number |
package |
string |
Prop | Type |
---|---|
cacheNotifications |
boolean |
packagesWhitelist |
string[] | null |