npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

capacitor-notification-reader

v1.2.0

Published

Capacitor plugin to read and persist Android notifications with RoomDB storage

Readme

capacitor-notification-reader

npm version npm downloads

Capacitor plugin to read active notifications on Android with persistent storage.

Features

  • Read Active Notifications: Access all currently active notifications from the notification drawer
  • Persistent Storage: Notifications are automatically stored in a RoomDB database when posted
  • Background Collection: Notifications are captured even when your app isn't running
  • Pagination Support: Efficiently retrieve stored notifications with pagination
  • Comprehensive Type Safety: Full TypeScript support with discriminated unions
  • Rich Notification Data: Access notification styles, actions, icons, and metadata

Install

npm install capacitor-notification-reader
npx cap sync

How It Works

Persistent Notification Storage

This plugin uses Android's NotificationListenerService combined with RoomDB to provide robust notification tracking:

  1. Notification Listener Service: Once you grant notification access, the Android NotificationListenerService runs in the background and receives all notifications system-wide.

  2. Automatic Storage: When a notification is posted, the service automatically:

    • Parses all notification data (title, text, style, actions, icons, etc.)
    • Stores it in a local RoomDB database
    • Notifies your app via the notificationPosted event listener (if the app is running)
  3. Background Operation: The listener service operates independently of your app:

    • Notifications are captured even when your app is closed
    • Data persists across app restarts
    • No battery-intensive polling required
  4. Dual Access Methods:

    • getActiveNotifications(): Returns currently visible notifications from the notification drawer
    • getNotifications(): Retrieves stored notifications from the database with pagination support

Database Schema

The RoomDB database stores comprehensive notification data including:

  • Primary key: UUID (automatically generated for each notification)
  • Basic fields: app name (human-readable), package name, title, text, timestamp
  • Icons: small icon, large icon, app icon (all as base64)
  • Metadata: category, style, channel ID, group info, priority
  • Style-specific data: big text, big picture, inbox lines, messaging conversations
  • Action buttons with inline reply support
  • Progress information for download/upload notifications
  • Call-style specific data (caller name)

Note: When the NotificationListenerService first connects (e.g., when your app is installed or after device reboot), it automatically loads all currently active notifications into the database. This ensures you have a complete history from the moment the service starts.

Usage Examples

Listen for Real-time Notifications

import { NotificationReader } from 'capacitor-notification-reader';

// Listen for notifications as they are posted
await NotificationReader.addListener('notificationPosted', (notification) => {
  console.log('New notification:', notification.title);
  console.log('Stored in DB with ID:', notification.id);
  // The notification is automatically saved to the database
});

Retrieve Stored Notifications with Pagination

import { NotificationReader } from 'capacitor-notification-reader';

// Get first batch (most recent notifications)
const { notifications } = await NotificationReader.getNotifications({
  limit: 20
});

// Get next batch using cursor (timestamp-based pagination)
if (notifications.length > 0) {
  const lastTimestamp = notifications[notifications.length - 1].timestamp;
  const { notifications: nextBatch } = await NotificationReader.getNotifications({
    cursor: lastTimestamp,
    limit: 20
  });
}

Type-Safe Notification Handling

import { NotificationStyle, NotificationCategory } from 'capacitor-notification-reader';

notifications.forEach((notification) => {
  // TypeScript automatically narrows the type
  switch (notification.style) {
    case NotificationStyle.MESSAGING:
      // notification is MessagingNotification
      console.log('Messages:', notification.messages);
      break;
    case NotificationStyle.BIG_PICTURE:
      // notification is BigPictureNotification
      console.log('Picture:', notification.bigPicture);
      break;
  }
});

Clear Notification History

import { NotificationReader } from 'capacitor-notification-reader';

// Delete all stored notifications from the database
await NotificationReader.deleteAllNotifications();
console.log('All notification history cleared');

// Note: This only clears the database, not the system notification drawer

Import Notifications

import { NotificationReader, NotificationStyle } from 'capacitor-notification-reader';

// Prepare notifications to import (e.g., from a backup or migration)
const notificationsToImport = [
  {
    id: 'notification-1',
    appName: 'WhatsApp',
    packageName: 'com.whatsapp',
    title: 'John Doe',
    text: 'Hey, how are you?',
    timestamp: Date.now() - 3600000, // 1 hour ago
    style: NotificationStyle.MESSAGING,
    category: 'msg',
    actions: [],
    isGroupSummary: false,
    isOngoing: false,
    autoCancel: true,
    isLocalOnly: false,
    priority: 0,
    number: 1,
    messages: [
      {
        text: 'Hey, how are you?',
        timestamp: Date.now() - 3600000,
        sender: 'John Doe'
      }
    ],
    conversationTitle: 'John Doe',
    isGroupConversation: false
  }
];

// Import notifications into the database
await NotificationReader.importNotifications({
  notifications: notificationsToImport
});
console.log('Notifications imported successfully');

// Verify import
const { notifications } = await NotificationReader.getNotifications({ limit: 10 });
console.log('Imported notifications:', notifications);

For more detailed examples, see TYPE_USAGE_EXAMPLES.md.

API

getActiveNotifications()

getActiveNotifications() => Promise<GetActiveNotificationsResult>

Gets all active notifications from the notification listener service.

Returns: Promise<GetActiveNotificationsResult>

Since: 1.0.0


openAccessSettings()

openAccessSettings() => Promise<{ enabled: boolean; }>

Opens the system settings page to allow the user to grant notification access to the app. The promise resolves when the user returns from settings with the current permission status.

Returns: Promise<{ enabled: boolean; }>

Since: 1.0.0


isAccessEnabled()

isAccessEnabled() => Promise<{ enabled: boolean; }>

Checks if the app has notification access enabled.

Returns: Promise<{ enabled: boolean; }>

Since: 1.0.0


getNotifications(...)

getNotifications(options?: GetNotificationsOptions | undefined) => Promise<GetNotificationsResult>

Retrieves notifications from the persistent Room database with optional filtering and cursor-based pagination. Notifications are cached when they are posted and can be queried later even after dismissal from the notification drawer.

| Param | Type | Description | | ------------- | --------------------------------------------------------------------------- | -------------------------------------- | | options | GetNotificationsOptions | - Cursor, limit, and filtering options |

Returns: Promise<GetNotificationsResult>

Since: 1.0.0


deleteAllNotifications()

deleteAllNotifications() => Promise<void>

Deletes all notifications from the database. This does not affect notifications in the system notification drawer.

Since: 1.0.0


getTotalCount()

getTotalCount() => Promise<{ count: number; }>

Gets the total count of notifications stored in the database. This count includes all notifications regardless of their status or type.

Returns: Promise<{ count: number; }>

Since: 1.0.0


getDatabaseSize()

getDatabaseSize() => Promise<{ sizeBytes: number; sizeMB: number; }>

Gets the current database size in bytes consumed by stored notifications. This can be used to monitor storage usage and determine if you're approaching your configured storage limit.

Returns: Promise<{ sizeBytes: number; sizeMB: number; }>

Since: 1.0.0


importNotifications(...)

importNotifications(options: ImportNotificationsOptions) => Promise<void>

Imports an array of notifications into the database. This method is useful for restoring previously exported notifications, migrating data from another source, or bulk-importing notification data.

Each notification will be inserted using REPLACE strategy, meaning if a notification with the same ID already exists, it will be updated.

| Param | Type | Description | | ------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------- | | options | ImportNotificationsOptions | - Object containing the array of notifications to import |

Since: 1.0.0


getInstalledApps()

getInstalledApps() => Promise<GetInstalledAppsResult>

Retrieves a list of all installed applications on the device. Returns app name, package name, app icon, and whether it's a system app.

Returns: Promise<GetInstalledAppsResult>

Since: 1.0.0


getConfig()

getConfig() => Promise<NotificationReaderConfig>

Gets the current configuration for the notification reader plugin.

Returns: Promise<NotificationReaderConfig>

Since: 1.0.0


setConfig(...)

setConfig(config: NotificationReaderConfig) => Promise<void>

Sets the configuration for the notification reader plugin. Changes take effect immediately for new notifications.

| Param | Type | Description | | ------------ | ----------------------------------------------------------------------------- | ------------------------------ | | config | NotificationReaderConfig | - Configuration options to set |

Since: 1.0.0


addListener('notificationPosted', ...)

addListener(eventName: 'notificationPosted', listenerFunc: (notification: NotificationItem) => void) => Promise<PluginListenerHandle>

Listen for notifications that are posted while the listener service is running. Fires with the freshly-captured notification payload.

| Param | Type | | ------------------ | ---------------------------------------------------------------------------------------- | | eventName | 'notificationPosted' | | listenerFunc | (notification: NotificationItem) => void |

Returns: Promise<PluginListenerHandle>


Interfaces

GetActiveNotificationsResult

Result returned by getActiveNotifications.

| Prop | Type | Description | | ------------------- | ------------------------------- | -------------------------------------------------------- | | notifications | NotificationItem[] | Array of active notifications with type-specific shapes. |

BigTextNotification

Big text style notification with expanded text content

| Prop | Type | Description | | ------------- | ------------------------------------------------------------------------ | -------------------------------- | | style | NotificationStyle.BIG_TEXT | Notification style template used | | bigText | string | The full expanded text content |

BigPictureNotification

Big picture style notification with an image

| Prop | Type | Description | | ------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------- | | style | NotificationStyle.BIG_PICTURE | Notification style template used | | bigPicture | string | Base64-encoded picture shown in expanded view | | pictureContentDescription | string | Content description for the picture |

InboxNotification

Inbox style notification with multiple lines

| Prop | Type | Description | | ---------------- | --------------------------------------------------------------------- | -------------------------------- | | style | NotificationStyle.INBOX | Notification style template used | | inboxLines | string[] | Array of text lines in the inbox |

MessagingNotification

Messaging style notification for chat/messaging apps

| Prop | Type | Description | | ------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------- | | style | NotificationStyle.MESSAGING | Notification style template used | | category | NotificationCategory.MESSAGE | Notification category (call, message, email, etc.) | | conversationTitle | string | Conversation title for group chats | | isGroupConversation | boolean | Whether this is a group conversation | | messages | NotificationMessage[] | Array of messages in the conversation |

NotificationMessage

Message in a messaging-style notification

| Prop | Type | Description | | --------------- | ------------------- | ------------------------ | | text | string | Message text | | timestamp | number | Timestamp of the message | | sender | string | Sender name |

ProgressNotification

Progress style notification for downloads, uploads, etc.

| Prop | Type | Description | | -------------- | ------------------------------------------------------------------------------ | -------------------------------------------------- | | style | NotificationStyle.DEFAULT | Notification style template used | | category | NotificationCategory.PROGRESS | Notification category (call, message, email, etc.) | | progress | NotificationProgress | Progress information |

NotificationProgress

Progress information for notifications with progress bars

| Prop | Type | Description | | ------------------- | -------------------- | ------------------------------------- | | current | number | Current progress value | | max | number | Maximum progress value | | indeterminate | boolean | Whether the progress is indeterminate |

CallNotification

Call notification

| Prop | Type | Description | | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | style | NotificationStyle.CALL | NotificationStyle.DEFAULT | Notification style template used | | category | NotificationCategory.CALL | NotificationCategory.MISSED_CALL | Notification category (call, message, email, etc.) | | callerName | string | Caller name |

MediaNotification

Media playback notification

| Prop | Type | Description | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | style | NotificationStyle.MEDIA | NotificationStyle.DECORATED_MEDIA | Notification style template used | | category | NotificationCategory.TRANSPORT | Notification category (call, message, email, etc.) |

GenericNotification

Generic notification that doesn't fit specific patterns

| Prop | Type | Description | | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | | style | NotificationStyle.DECORATED_CUSTOM | NotificationStyle.DEFAULT | Notification style template used |

GetNotificationsResult

Result returned by getNotifications.

| Prop | Type | Description | | ------------------- | ------------------------------- | ----------------------------------------- | | notifications | NotificationItem[] | Array of notifications from the database. |

GetNotificationsOptions

Options for getNotifications.

| Prop | Type | Description | Default | | ------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | | cursor | number | Return notifications whose timestamp is strictly less than this value (in ms). Use the timestamp from the last item of the previous page when paginating. | | | limit | number | Maximum number of notifications to retrieve. | 10 | | filter | NotificationFilter | Optional filter criteria applied on the stored notifications. | |

NotificationFilter

Advanced filters for querying stored notifications. Each filter is optional and multiple filters are combined with AND logic.

| Prop | Type | Description | | ------------------------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------- | | textContains | string | Match notifications whose text contains the provided value (case-sensitive). | | titleContains | string | Match notifications whose title contains the provided value (case-sensitive). | | textContainsInsensitive | string | Match notifications whose text contains the provided value (case-insensitive). | | titleContainsInsensitive | string | Match notifications whose title contains the provided value (case-insensitive). | | appNames | string[] | Only return notifications whose appName exactly matches one of the supplied names. | | packageName | string | Filter by package name of the posting application. | | category | string | Filter by notification category. | | style | string | Filter by notification style template. | | isOngoing | boolean | Filter for ongoing (non-dismissible) notifications only. | | isGroupSummary | boolean | Filter for group summary notifications only. | | channelId | string | Filter by notification channel ID (Android 8+). | | afterTimestamp | number | Only return notifications posted after this timestamp (in milliseconds). Creates a lower bound for the time range. | | beforeTimestamp | number | Only return notifications posted before this timestamp (in milliseconds). Creates an upper bound for the time range. |

ImportNotificationsOptions

Options for importNotifications.

| Prop | Type | Description | | ------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | notifications | NotificationItem[] | Array of notification items to import into the database. Each notification should conform to the NotificationItem type structure. |

GetInstalledAppsResult

Result returned by getInstalledApps.

| Prop | Type | Description | | ---------- | --------------------------- | ---------------------------------------------------- | | apps | InstalledApp[] | Array of installed applications with their metadata. |

InstalledApp

Information about an installed application.

| Prop | Type | Description | | ----------------- | -------------------- | ---------------------------------------------- | | packageName | string | The package name of the app. | | appName | string | The human-readable name of the app. | | appIcon | string | Base64-encoded PNG of the app's launcher icon. | | isSystemApp | boolean | Whether the app is a system app. |

NotificationReaderConfig

Configuration options for the notification reader plugin.

| Prop | Type | Description | Default | | --------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | | filterOngoing | boolean | Whether to filter out ongoing (non-dismissible) notifications. When true, ongoing notifications will be filtered out and not stored. | true | | filterTransport | boolean | Whether to filter out transport category notifications. When true, notifications with category 'transport' will be filtered out and not stored. | true | | storageLimit | number | Storage limit for notifications in megabytes (MB). When the database exceeds this limit, older notifications will be removed using FIFO. Set to undefined for unlimited storage. | 500 |

PluginListenerHandle

| Prop | Type | | ------------ | ----------------------------------------- | | remove | () => Promise<void> |

Type Aliases

NotificationItem

Union type of all specific notification types. Use discriminated union on 'style' and 'category' for type narrowing.

Type narrowing examples:

  • For BigTextNotification: check notification.style === <a href="#notificationstyle">NotificationStyle</a>.BIG_TEXT
  • For BigPictureNotification: check notification.style === <a href="#notificationstyle">NotificationStyle</a>.BIG_PICTURE
  • For InboxNotification: check notification.style === <a href="#notificationstyle">NotificationStyle</a>.INBOX
  • For MessagingNotification: check notification.style === <a href="#notificationstyle">NotificationStyle</a>.MESSAGING
  • For ProgressNotification: check notification.category === <a href="#notificationcategory">NotificationCategory</a>.PROGRESS
  • For CallNotification: check category is CALL or MISSED_CALL
  • For MediaNotification: check style is MEDIA or DECORATED_MEDIA

BigTextNotification | BigPictureNotification | InboxNotification | MessagingNotification | ProgressNotification | CallNotification | MediaNotification | GenericNotification

Enums

NotificationStyle

| Members | Value | | ---------------------- | -------------------------------------------- | | BIG_TEXT | 'BigTextStyle' | | BIG_PICTURE | 'BigPictureStyle' | | INBOX | 'InboxStyle' | | MESSAGING | 'MessagingStyle' | | MEDIA | 'MediaStyle' | | CALL | 'CallStyle' | | DECORATED_CUSTOM | 'DecoratedCustomViewStyle' | | DECORATED_MEDIA | 'DecoratedMediaCustomViewStyle' | | DEFAULT | 'default' |

NotificationCategory

| Members | Value | | ---------------------- | ------------------------------- | | ALARM | 'alarm' | | CALL | 'call' | | EMAIL | 'email' | | ERROR | 'err' | | EVENT | 'event' | | LOCATION_SHARING | 'location_sharing' | | MESSAGE | 'msg' | | MISSED_CALL | 'missed_call' | | NAVIGATION | 'navigation' | | PROGRESS | 'progress' | | PROMO | 'promo' | | RECOMMENDATION | 'recommendation' | | REMINDER | 'reminder' | | SERVICE | 'service' | | SOCIAL | 'social' | | STATUS | 'status' | | STOPWATCH | 'stopwatch' | | SYSTEM | 'sys' | | TRANSPORT | 'transport' | | VOICEMAIL | 'voicemail' | | WORKOUT | 'workout' | | UNKNOWN | 'unknown' |

Contributing

See CONTRIBUTING.md for details on how to contribute to this project.

Release Process

This package uses npm Trusted Publishers with OIDC for secure, automated releases. Releases are triggered automatically when commits are pushed to the main branch.

Setup (One-time)

Configure the trusted publisher on npm:

  1. Go to your package settings on npmjs.com
  2. Navigate to "Publishing access" → "Trusted Publisher"
  3. Select "GitHub Actions"
  4. Configure:
    • Organization/User: WhyAsh5114
    • Repository: capacitor-notification-reader
    • Workflow filename: release.yml

No npm tokens needed! The workflow uses OpenID Connect (OIDC) for authentication.

Commit Convention

Follow Conventional Commits for your commit messages:

  • feat: - New features (triggers minor version bump)
  • fix: - Bug fixes (triggers patch version bump)
  • docs: - Documentation changes
  • chore: - Maintenance tasks
  • BREAKING CHANGE: - Breaking changes (triggers major version bump)

Example:

git commit -m "feat: add support for notification icons"
git commit -m "fix: resolve crash when notification has no title"

The CI pipeline will automatically:

  1. Build the package
  2. Determine version bump based on commits
  3. Create a GitHub release with changelog
  4. Publish to npm with provenance attestation