项目作者: flytesoft-software

项目描述 :
A Capacitor plugin that allows continuous background work by using a persistent notification in Android.
高级语言: Java
项目地址: git://github.com/flytesoft-software/capacitor-persistent-notification.git
创建时间: 2020-07-03T00:45:48Z
项目社区:https://github.com/flytesoft-software/capacitor-persistent-notification

开源协议:MIT License

下载


Persistent Notification for Capacitor

A Capacitor plugin that allows a continuous background service by using a persistent notification in Android. Your background task/service is written in JavaScript, no need for platform specific code (except that required of enabling a Capacitor plugin.)

Based upon, though not a fork of, the Cordova Background Mode Plugin.

In order to allow an app written in HTML5/Javascript/CSS to continuously run in the background using a persistent foreground service notification in Android.

This plugin uses the new Ionic/Capacitor plugin system

Unfortunately, because of system limitations, this plugin ONLY works on Android! The plugin calls are NO-OP on the web platform, and non-existent in iOS and Electron. Further research may allow a persistent background service in Electron. iOS does not have a system that allows a persistent background service. (I understand there are hacky methods to make it work in iOS, but until there is a proper API I plan no updates for iOS.)

KNOWN ISSUE LIMITATION: Unfortunately because the JavaScript code used to run a Capacitor app lives in an Android Activity, it is not currently possible to restart a service upon shutdown, crash, or reboot. See Android limitation. I am currently researching possible solutions. For now try to keep memory consumption to a minimum while app is in “background” state.

Examples | API | Changelog | Donate

NPM Repository

capacitor-persistent-notification

Installation

Ensure Android is added to your Capacitor based project:

  1. npx cap add android

Use NPM in your project directory to install the plugin.

  1. npm install capacitor-persistent-notification@latest --save
  2. npx cap update

Getting Started

Ensure your project includes the Capacitor plugin code.

Standard HTML import:

  1. <script src="capacitor.js"></script>
  1. const { Plugins } = Capacitor;
  2. const { PersistentNotification } = Plugins;

or Node Imports:

  1. import { Plugins } from '@capacitor/core';
  2. const { PersistentNotification } = Plugins;

Be sure to add the plugin to your MainActivity in your Android project:

  1. import com.flytesoft.persistent.notification.PersistentNotification;
  2. public class MainActivity extends BridgeActivity {
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. // Initializes the Bridge
  7. this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {
  8. {
  9. // Additional plugins you've installed go here
  10. // Ex: add(TotallyAwesomePlugin.class);
  11. add(PersistentNotification.class);
  12. }
  13. });
  14. }
  15. }

Add the foreground service permission to the AndroidManifest.xml:

  1. <!-- Permissions -->
  2. <uses-permission android:name="android.permission.FOREGROUND_SERVICE" ></uses-permission>

Example Code

It is recommended, although not required, to open your notification upon your app closing:

  1. const { PersistentNotification, App, BackgroundTask } = Plugins;
  2. ...
  3. let listener = null;
  4. App.addListener('appStateChange', (state) => {
  5. // Listen for user clicks on the notification.
  6. // OK to listen before opening.
  7. listener = constPersistentNotification.addListener('notificationclick', ({ action } => {
  8. console.log("Persistent notification click: ", action);
  9. if(!action) // A button was NOT clicked.
  10. {
  11. // Put the app in the foreground
  12. // and close the notification, if desired.
  13. PersistentNotification.appToForeground();
  14. PersistentNotification.close();
  15. }
  16. else // A button was clicked by the user.
  17. {
  18. if(action === 'button-click2')
  19. {
  20. console.log("Button 2 was clicked!");
  21. }
  22. }
  23. });
  24. if (!state.isActive) // App has gone inactive or closed
  25. {
  26. // Get some work done before the app closes completely.
  27. const taskId = BackgroundTask.beforeExit(async () => {
  28. try
  29. {
  30. await PersistentNotification.open({
  31. title: "Background Forever!",
  32. icon: "icons/icon.png",
  33. // Icon asset exist in www/icons/icon.png
  34. // Icon asset always based upon TLD and
  35. // NOT the location of your code.
  36. body: "We can run continuously!",
  37. actions: [{
  38. title: "button",
  39. action: "button-click",
  40. icon: "icons/icon.png"
  41. },
  42. {
  43. title: "button2",
  44. action: "button-click2",
  45. icon: "icons/icon.png"
  46. }]
  47. });
  48. // See if the notification is open.
  49. const { isOpen } = await PersistentNotification.getState();
  50. console.log("Is open: ", isOpen);
  51. }
  52. catch(e)
  53. {
  54. console.log("Unable to start background service: ", e);
  55. }
  56. // Let the app close.
  57. BackgroundTask.finish({
  58. taskId
  59. });
  60. });
  61. /**
  62. * It is recommended you stop any code that updates the DOM:
  63. * The DOM will still be 'awake' but not visible to the user.
  64. * So save CPU power.
  65. *
  66. * stopVisualTasks();
  67. * */
  68. // Now do your continuous background task.
  69. // Update the notification as necessary.
  70. let interval = 1;
  71. setInterval(() => {
  72. PersistentNotification.update({
  73. body: `Seconds gone by: ${interval}`);
  74. interval++;
  75. }, 1000);
  76. }
  77. else // App is now opening or resuming.
  78. {
  79. // OK to close un-opened notification.
  80. PersistentNotification.close().
  81. catch(e => {
  82. console.log("Trouble closing the persistent notification: ", e);
  83. });
  84. // remove the listener.
  85. if(listener != null)
  86. {
  87. listener.remove();
  88. listener = null;
  89. }
  90. }
  91. });

API

The API is similar to the the standard ES6+ Notification API. However, the PersistentNotification class is completely static and all methods return Promises, as do most of the Capacitor APIs and plugins.

PersistentNotification.open([options]) ⇒ Promise

A method to open and configure your persistent notification. Returns success upon notification opening. Configuration options are only optional if you have previously called the update method.

Kind: Static instance method of PersistentNotification
Category: async
Fulfil: undefined
Throws: Error

| Param | Type | Description |
| —- | —- | —- |
| [options] | object | Similar to the Notification API options. |
| [options.title] | string | Set the title of the notification. Limited HTML may be used (Required) |
| [options.body] | string | Set the content or body area of the notification. Limited HTML may be used (Required)|
| [options.color] | string | Set the highlight color of the notification. Hex code or color names only). If undefined or invalid, defaults to blue. |
| [options.actions] | Array.<NotificationAction> | An array of one or more buttons to be included. |
| [options.icon] | string | Location of the icon to be displayed in the status bar for the notification. Must use a relative path to icon resource from your top level directory. If undefined or invalid, a default icon is provided. |

| [options.badge] | string | Location of a large (badge type) icon to be displayed in the notification. Must use a relative path to the resource from your top level directory. If undefined or invalid, no badge is displayed. |

PersistentNotification.update([options]) ⇒ Promise

A method to configure and/or update a current notification. If a notification is not already open your configuration will be maintained until open is called. Only update options you need to update. See open for parameters.

Kind: Static instance method of PersistentNotification
Category: async
Fulfil: undefined
Throws: Error


PersistentNotification.close(void) ⇒ Promise

Closes the notification. If the notification is not open, the method is NO-OP and returns success. If unable to close the notification an error is thrown.

Kind: Static instance method of PersistentNotification
Category: async
Fulfil: undefined
Throws: Error


PersistentNotification.appToForeground(void) ⇒ Promise

Brings the main application view or webview into the foreground. If the app is already in the foreground the method is NO-OP. Useful to call when the user has clicked on the notification.

Kind: Static instance method of PersistentNotification
Category: async
Fulfil: undefined


PersistentNotification.getState(void) ⇒ Promise

A promise that returns whether the notification is currently open.

Kind: Static instance method of PersistentNotification
Category: async
Fulfil: state


PersistentNotification.addListener(eventName: ‘notificationclick’, listenerFunc: (data: action) => void) : ListenerHandle

Kind: Static instance method of PersistentNotification
Category: EventListener
Returns: ListenerHandle

Add an event listener when the notification is clicked. The data object is passed to the listener function.
| Param | Type | Description |
| —- | —- | —- |
| data | object | Data object passed to event listener function |
| data.action | string | Actions string value, if a button is clicked the value will be the ‘action’ or title of that button. An empty string indicates the notification was clicked by the user. |


ListenerHandle object

Category: object

Object containing the event listener for the notification. Call remove() to delete the event listener.

Param Type Description
remove function Remove the event listener.

NotificationAction object

Category: object

Object containing the options for a button to be displayed in the notification, similar to the NotificationAction object in ES6+.

Param Type Description
[title] string The title of the button (required).
[action] string The action data of the button, will be returned upon ‘notificationclick’ event. If undefined, the title will be used.
[icon] string Location of the icon to be displayed in the button. Must use a relative path to icon resource from your top level directory. If undefined or invalid, a default icon is provided. The icon is NOT displayed in Android 9.0+.

state object

Category: object

Object containing the state information of the notification

Param Type Description
[isOpen] boolean Whether the notification is open or not.

Changelog

0.9.5

  • Kill some memory leaks.
  • Attempt to ready code to handle service crashes/restarts.

0.9.4

  • Performance improvements.
  • Longer text may be used in the body.
  • Body and title of notification may use limited HTML markup.
  • Readme fixes.

0.9.3

  • Readme fixes.

0.9.2

  • Readme fixes.

0.9.1

  • Readme fixes.
  • Distribution file fixes.

0.9.0

  • Initial commit.

Donation / Tips


If you found this project useful and you would like to help buy me a cup of coffee, consider a donation via Paypal. (Not tax deductible. Non-charitable.) Either way, I am hoping you find this project useful.

License

MIT