{"id":27072594,"url":"https://github.com/jiusanzhou/flutter_notification_listener","last_synced_at":"2025-04-05T23:18:40.620Z","repository":{"id":56829793,"uuid":"365702607","full_name":"jiusanzhou/flutter_notification_listener","owner":"jiusanzhou","description":"Flutter plugin to listen for and  interact with all incoming notifications for Android. 一个监听手机通知的插件。","archived":false,"fork":false,"pushed_at":"2024-11-23T03:39:18.000Z","size":102,"stargazers_count":41,"open_issues_count":21,"forks_count":50,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-01T17:08:52.125Z","etag":null,"topics":["android","auto-reply","background","flutter","flutter-plugin","incoming-notifications","interactive","notifications","scraping","zoe-lab"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/flutter_notification_listener","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jiusanzhou.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"zoeim","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null}},"created_at":"2021-05-09T08:20:54.000Z","updated_at":"2025-01-13T13:18:43.000Z","dependencies_parsed_at":"2024-01-05T12:43:12.093Z","dependency_job_id":"2098a73d-37e9-4cd6-ad4d-f1df42e4b1bb","html_url":"https://github.com/jiusanzhou/flutter_notification_listener","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiusanzhou%2Fflutter_notification_listener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiusanzhou%2Fflutter_notification_listener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiusanzhou%2Fflutter_notification_listener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiusanzhou%2Fflutter_notification_listener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jiusanzhou","download_url":"https://codeload.github.com/jiusanzhou/flutter_notification_listener/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247411543,"owners_count":20934699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","auto-reply","background","flutter","flutter-plugin","incoming-notifications","interactive","notifications","scraping","zoe-lab"],"created_at":"2025-04-05T23:18:40.044Z","updated_at":"2025-04-05T23:18:40.614Z","avatar_url":"https://github.com/jiusanzhou.png","language":"Kotlin","funding_links":["https://ko-fi.com/zoeim"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# flutter_notification_listener\n\n[![Version](https://img.shields.io/pub/v/flutter_notification_listener.svg)](https://pub.dartlang.org/packages/flutter_notification_listener)\n[![pub points](https://badges.bar/flutter_notification_listener/pub%20points)](https://pub.dev/packages/flutter_notification_listener/score)\n[![popularity](https://badges.bar/flutter_notification_listener/popularity)](https://pub.dev/packages/flutter_notification_listener/score)\n[![likes](https://badges.bar/flutter_notification_listener/likes)](https://pub.dev/packages/flutter_notification_listener/score)\n[![License](https://img.shields.io/badge/license-AL2-blue.svg)](https://github.com/jiusanzhou/flutter_notification_listener/blob/master/LICENSE)\n\nFlutter plugin to listen for all incoming notifications for Android.\n\n\u003c/div\u003e\n\n---\n\n## Features\n\n- **Service**: start a service to listen the notifications.\n- **Simple**: it's simple to access notification's fields.\n- **Backgrounded**: execute the dart code in the background and auto start the service after reboot.\n- **Interactive**: the notification is interactive in flutter.\n\n## Installtion\n\nOpen the `pubspec.yaml` file located inside the app folder, and add `flutter_notification_listener`: under `dependencies`.\n```yaml\ndependencies:\n  flutter_notification_listener: \u003clatest_version\u003e\n```\n\nThe latest version is \n[![Version](https://img.shields.io/pub/v/flutter_notification_listener.svg)](https://pub.dartlang.org/packages/flutter_notification_listener)\n\nThen you should install it,\n- From the terminal: Run `flutter pub get`.\n- From Android Studio/IntelliJ: Click Packages get in the action ribbon at the top of `pubspec.yaml`.\n- From VS Code: Click Get Packages located in right side of the action ribbon at the top of `pubspec.yaml`.\n\n## Quick Start\n\n**1. Register the service in the manifest**\n\nThe plugin uses an Android system service to track notifications. To allow this service to run on your application, the following code should be put inside the Android manifest, between the `application` tags.\n\n```xml\n\u003cservice android:name=\"im.zoe.labs.flutter_notification_listener.NotificationsHandlerService\"\n    android:label=\"Flutter Notifications Handler\"\n    android:permission=\"android.permission.BIND_NOTIFICATION_LISTENER_SERVICE\"\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.service.notification.NotificationListenerService\" /\u003e\n    \u003c/intent-filter\u003e\n\u003c/service\u003e\n```\n\nAnd don't forget to add the permissions to the manifest,\n```xml\n\u003cuses-permission android:name=\"android.permission.WAKE_LOCK\" /\u003e\n\u003cuses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" /\u003e\n```\n\n**2. Init the plugin and add listen handler**\n\nWe have a default static event handler which send event with a channel.\nSo if you can listen the event in the ui logic simply.\n\n```dart\n// define the handler for ui\nvoid onData(NotificationEvent event) {\n    print(event.toString());\n}\n\nFuture\u003cvoid\u003e initPlatformState() async {\n    NotificationsListener.initialize();\n    // register you event handler in the ui logic.\n    NotificationsListener.receivePort.listen((evt) =\u003e onData(evt));\n}\n```\n\n**3. Check permission and start the service**\n\n```dart\nvoid startListening() async {\n    print(\"start listening\");\n    var hasPermission = await NotificationsListener.hasPermission;\n    if (!hasPermission) {\n        print(\"no permission, so open settings\");\n        NotificationsListener.openPermissionSettings();\n        return;\n    }\n\n    var isR = await NotificationsListener.isRunning;\n\n    if (!isR) {\n        await NotificationsListener.startService();\n    }\n\n    setState(() =\u003e started = true);\n}\n```\n\n---\n\nPlease check the [./example/lib/main.dart](./example/lib/main.dart) for more detail.\n\n## Usage\n\n### Start the service after reboot\n\nIt's every useful while you want to start listening notifications automatically after reboot.\n\nRegister a broadcast receiver in the `AndroidManifest.xml`,\n```xml\n\u003creceiver android:name=\"im.zoe.labs.flutter_notification_listener.RebootBroadcastReceiver\"\n    android:enabled=\"true\"\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.intent.action.BOOT_COMPLETED\" /\u003e\n    \u003c/intent-filter\u003e\n\u003c/receiver\u003e\n```\n\nThen the listening service will start automatically when the system fired the `BOOT_COMPLETED` intent.\n\n\nAnd don't forget to add the permissions to the manifest,\n```xml\n\u003cuses-permission android:name=\"android.permission.WAKE_LOCK\" /\u003e\n\u003cuses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" /\u003e\n\u003c!-- this pemission is for auto start service after reboot --\u003e\n\u003cuses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/\u003e\n```\n\n### Execute task without UI thread\n\n\u003e You should know that the function `(evt) =\u003e onData(evt)` would **not be called** if the ui thread is not running.\n\n**:warning: It's recommended that you should register your own static function `callbackHandle` to handle the event which make sure events consumed.**\n\nThat means the `callbackHandle` static function is guaranteed, while the channel handle function is not. This is every useful when you should persist the events to the database.\n\n\u003e For Flutter 3.x: \nAnnotate the _callback function with `@pragma('vm:entry-point')` to prevent Flutter from stripping out this function on services.\n\nWe want to run some code in background without UI thread, like persist the notifications to database or storage.\n\n1. Define your own callback to handle the incoming notifications.\n    ```dart\n    @pragma('vm:entry-point')\n    static void _callback(NotificationEvent evt) {\n        // persist data immediately\n        db.save(evt)\n\n        // send data to ui thread if necessary.\n        // try to send the event to ui\n        print(\"send evt to ui: $evt\");\n        final SendPort send = IsolateNameServer.lookupPortByName(\"_listener_\");\n        if (send == null) print(\"can't find the sender\");\n        send?.send(evt);\n    }\n    ```\n\n2. Register the handler when invoke the `initialize`.\n    ```dart\n    Future\u003cvoid\u003e initPlatformState() async {\n        // register the static to handle the events\n        NotificationsListener.initialize(callbackHandle: _callback);\n    }\n    ```\n\n3. Listen events in the UI thread if necessary.\n    ```dart\n    // define the handler for ui\n    void onData(NotificationEvent event) {\n        print(event.toString());\n    }\n\n    Future\u003cvoid\u003e initPlatformState() async {\n        // ...\n        // register you event handler in the ui logic.\n        NotificationsListener.receivePort.listen((evt) =\u003e onData(evt));\n    }\n    ```\n\n### Change notification of listening service\n\nBefore you start the listening service, you can offer some parameters.\n```dart\nawait NotificationsListener.startService({\n    bool foreground = true, // use false will not promote to foreground and without a notification\n    String title = \"Change the title\",\n    String description = \"Change the text\",\n});\n```\n\n### Tap the notification\n\nWe can tap the notification if it can be triggered in the flutter side.\n\n\nFor example, tap the notification automatically when the notification arrived.\n\n```dart\n// define the handler for ui\nvoid onData(NotificationEvent event) {\n    print(event.toString());\n    // tap the notification automatically\n    // usually remove the notification\n    if (event.canTap) event.tap();\n}\n```\n\n### Tap action of the notification\n\nThe notifications from some applications will setted the actions.\nWe can interact with the notificaions in the flutter side.\n\nFor example, make  the notification as readed automatically when the notification arrived.\n\n```dart\n// define the handler for ui\nvoid onData(NotificationEvent event) {\n    print(event.toString());\n    \n    events.actions.forEach(act =\u003e {\n        // semantic code is 2 means this is an ignore action\n        if (act.semantic == 2) {\n            act.tap();\n        }\n    })\n}\n```\n\n### Reply to conversation of the notification\n\nAndroid provider a quick replying method in the notification.\nSo we can use this to implement a reply logic in the flutter.\n\nFor example, reply to the conversation automatically when the notification arrived.\n\n```dart\n// define the handler for ui\nvoid onData(NotificationEvent event) {\n    print(event.toString());\n    \n    events.actions.forEach(act =\u003e {\n        // semantic is 1 means reply quick\n        if (act.semantic == 1) {\n            Map\u003cString, dynamic\u003e map = {};\n            act.inputs.forEach((e) {\n                print(\"set inputs: ${e.label}\u003c${e.resultKey}\u003e\");\n                map[e.resultKey] = \"Auto reply from flutter\";\n            });\n\n            // send to the data\n            act.postInputs(map);\n        }\n    })\n}\n```\n\n## API Reference\n\n### Object `NotificationEvent`\n\nFields of `NotificationEvent`:\n- `uniqueId`: `String`, unique id of the notification which generated from `key`.\n- `key`: `String`, key of the status bar notification, required android sdk \u003e= 20.\n- `packageName`: `String`, package name of the application which notification posted by.\n- `uid`: `int`, uid of the notification, required android sdk \u003e= 29.\n- `channelId`: `String` channel if of the notification, required android sdk \u003e= 26.\n- `id`: `int`, id of the notification.\n- `createAt`: `DateTime`, created time of the notfication in the flutter side.\n- `timestamp`: `int`, post time of the notfication.\n- `title`: `title`, title of the notification.\n- `text`: `String`, text of the notification.\n- `hasLargeIcon`: `bool`, if this notification has a large icon.\n- `largeIcon`: `Uint8List`, large icon of the notification which setted by setLargeIcon. To display as a image use the Image.memory widget.\n- `canTap`: `bool`, if this notification has content pending intent.\n- `raw`: `Map\u003cString, dynamic\u003e`, the original map of this notification, you can get all fields.\n\nOther original fields in `raw` which not assgin to the class:\n- `subText`: `String`, subText of the notification.\n- `summaryText`: `String`, summaryText of the notification.\n- `textLines`: `List\u003cString\u003e`, multi text lines of the notification.\n- `showWhen`: `bool`, if show the time of the notification.\n\nMethods for notification:\n- `Future\u003cbool\u003e tap()`: tap the notification if it can be triggered, you should check `canTap` first. Normally will clean up the notification.\n- `Future\u003cdynamic\u003e getFull()`: get the full notification object from android.\n\n### Object `Action`\n\nFields of `Action`:\n- `id`: `int`, the index of the action in the actions array\n- `title`: `String`, title of the action\n- `semantic`: `int`, semantic type of the action, check below for details\n- `inputs`: `ActionInput`, emote inputs list of the action\n\nAction's semantic types:\n```\nSEMANTIC_ACTION_ARCHIVE = 5;\nSEMANTIC_ACTION_CALL = 10;\nSEMANTIC_ACTION_DELETE = 4;\nSEMANTIC_ACTION_MARK_AS_READ = 2;\nSEMANTIC_ACTION_MARK_AS_UNREAD = 3;\nSEMANTIC_ACTION_MUTE = 6;\nSEMANTIC_ACTION_NONE = 0;\nSEMANTIC_ACTION_REPLY = 1;\nSEMANTIC_ACTION_THUMBS_DOWN = 9;\nSEMANTIC_ACTION_THUMBS_UP = 8;\nSEMANTIC_ACTION_UNMUTE = 7;\n```\n\nFor more details, please see [Notification.Action Constants](https://developer.android.com/reference/android/app/Notification.Action#constants_1).\n\n\nMethods of `Action`:\n- `Future\u003cbool\u003e tap()`: tap the action of the notification. If action's semantic code is `1`, it can't be tapped.\n- `Future\u003cbool\u003e postInputs(Map\u003cString, dynamic\u003e map)`: post inputs to the notification, useful for replying automaticly. Only works when semantic code  is `1`.\n\n### Object `ActionInput`\n\nFields of `ActionInput`:\n- `label`: `String`, label for input.\n- `resultKey`: `String`, result key for input. Must use correct to post data to inputs.\n\n\n### Class `NotificationsListener`\n\nFields of `NotificationsListener`:\n- `isRunning`: `bool`, check if the listener service is running.\n- `hasPermission`: `bool`, check if grant the permission to start the listener service.\n- `receivePort`: `ReceivePort`, default receive port for listening events.\n\nStatic methods of `NotificationsListener`:\n- `Future\u003cvoid\u003e initialize()`: initialize the plugin, must be called at first.\n- `Future\u003cvoid\u003e registerEventHandle(EventCallbackFunc callback)`: register the event handler which will be called from android service, **shoube be static function**.\n- `Future\u003cvoid\u003e openPermissionSettings()`: open the system listen notifactoin permission setting page.\n- `Future\u003cbool?\u003e startService({...})`: start the listening service. arguments,\n    - `foreground`: `bool`, optional, promote the service to foreground.\n    - `subTitle`: `String`, optional, sub title of the service's notification.\n    - `title`: `String`, optional, title of the service's notification.\n    - `description`: `String`, optional, text contenet of the service's notification.\n    - `showWhen`: `bool`, optional\n- `Future\u003cbool?\u003e stopService()`: stop the listening service.\n- `Future\u003cvoid\u003e promoteToForeground({...})` proomte the service to the foreground. *Arguments are same `startService`*.\n- `Future\u003cvoid\u003e demoteToBackground()`: demote the service to background.\n\n## Known Issues\n\n- If the service is not foreground, service will start failed after reboot.\n\n## Support\n\nDid you find this plugin useful? Please consider to make a donation to help improve it!\n\n## Contributing\n\nContributions are always welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiusanzhou%2Fflutter_notification_listener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjiusanzhou%2Fflutter_notification_listener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiusanzhou%2Fflutter_notification_listener/lists"}