diff --git a/app/README.md b/app/README.md index 9f9e0fd80..5c0ec03ea 100644 --- a/app/README.md +++ b/app/README.md @@ -77,6 +77,8 @@ const checkAppLaunchUrl = async () => { * [`getLaunchUrl()`](#getlaunchurl) * [`minimizeApp()`](#minimizeapp) * [`addListener('appStateChange', ...)`](#addlistenerappstatechange) +* [`addListener('pause', ...)`](#addlistenerpause) +* [`addListener('resume', ...)`](#addlistenerresume) * [`addListener('appUrlOpen', ...)`](#addlistenerappurlopen) * [`addListener('appRestoredResult', ...)`](#addlistenerapprestoredresult) * [`addListener('backButton', ...)`](#addlistenerbackbutton) @@ -171,7 +173,12 @@ Only available for Android. addListener(eventName: 'appStateChange', listenerFunc: StateChangeListener) => Promise & PluginListenerHandle ``` -Listen for changes in the App's active state (whether the app is in the foreground or background) +Listen for changes in the app or the activity states. + +On iOS it's fired when the native [UIApplication.willResignActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622973-willresignactivenotification) and +[UIApplication.didBecomeActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622953-didbecomeactivenotification) events get fired. +On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) and [onStop](https://developer.android.com/reference/android/app/Activity#onStop()) methods gets called. +On Web it's fired when the document's visibilitychange gets fired. | Param | Type | | ------------------ | ------------------------------------------------------------------- | @@ -185,6 +192,55 @@ Listen for changes in the App's active state (whether the app is in the foregrou -------------------- +### addListener('pause', ...) + +```typescript +addListener(eventName: 'pause', listenerFunc: () => void) => Promise & PluginListenerHandle +``` + +Listen for when the app or the activity are paused. + +On iOS it's fired when the native [UIApplication.didEnterBackgroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1623071-didenterbackgroundnotification) event gets fired. +On Android it's fired when the Capacitor's Activity [onPause](https://developer.android.com/reference/android/app/Activity#onPause()) method gets called. +On Web it's fired when the document's visibilitychange gets fired and document.hidden is true. + +| Param | Type | +| ------------------ | -------------------------- | +| **`eventName`** | 'pause' | +| **`listenerFunc`** | () => void | + +**Returns:** Promise<PluginListenerHandle> & PluginListenerHandle + +**Since:** 4.1.0 + +-------------------- + + +### addListener('resume', ...) + +```typescript +addListener(eventName: 'resume', listenerFunc: () => void) => Promise & PluginListenerHandle +``` + +Listen for when the app or activity are resumed. + +On iOS it's fired when the native [UIApplication.willEnterForegroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622944-willenterforegroundnotification) event gets fired. +On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) method gets called, +but only after resume has fired first. +On Web it's fired when the document's visibilitychange gets fired and document.hidden is false. + +| Param | Type | +| ------------------ | -------------------------- | +| **`eventName`** | 'resume' | +| **`listenerFunc`** | () => void | + +**Returns:** Promise<PluginListenerHandle> & PluginListenerHandle + +**Since:** 4.1.0 + +-------------------- + + ### addListener('appUrlOpen', ...) ```typescript diff --git a/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java b/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java index 1f5727931..e09c362ea 100644 --- a/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java +++ b/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java @@ -21,6 +21,9 @@ public class AppPlugin extends Plugin { private static final String EVENT_URL_OPEN = "appUrlOpen"; private static final String EVENT_STATE_CHANGE = "appStateChange"; private static final String EVENT_RESTORED_RESULT = "appRestoredResult"; + private static final String EVENT_PAUSE = "pause"; + private static final String EVENT_RESUME = "resume"; + private boolean hasPausedEver = false; public void load() { bridge @@ -132,6 +135,21 @@ protected void handleOnNewIntent(Intent intent) { notifyListeners(EVENT_URL_OPEN, ret, true); } + @Override + protected void handleOnPause() { + super.handleOnPause(); + hasPausedEver = true; + notifyListeners(EVENT_PAUSE, null); + } + + @Override + protected void handleOnResume() { + super.handleOnResume(); + if (hasPausedEver) { + notifyListeners(EVENT_RESUME, null); + } + } + @Override protected void handleOnDestroy() { unsetAppListeners(); diff --git a/app/ios/Plugin/AppPlugin.swift b/app/ios/Plugin/AppPlugin.swift index 361232e72..e97412711 100644 --- a/app/ios/Plugin/AppPlugin.swift +++ b/app/ios/Plugin/AppPlugin.swift @@ -19,6 +19,14 @@ public class AppPlugin: CAPPlugin { ]) }) + observers.append(NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in + self?.notifyListeners("pause", data: nil) + }) + + observers.append(NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in + self?.notifyListeners("resume", data: nil) + }) + } deinit { diff --git a/app/src/definitions.ts b/app/src/definitions.ts index d4637e4c3..33f7583ab 100644 --- a/app/src/definitions.ts +++ b/app/src/definitions.ts @@ -172,7 +172,12 @@ export interface AppPlugin { minimizeApp(): Promise; /** - * Listen for changes in the App's active state (whether the app is in the foreground or background) + * Listen for changes in the app or the activity states. + * + * On iOS it's fired when the native [UIApplication.willResignActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622973-willresignactivenotification) and + * [UIApplication.didBecomeActiveNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622953-didbecomeactivenotification) events get fired. + * On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) and [onStop](https://developer.android.com/reference/android/app/Activity#onStop()) methods gets called. + * On Web it's fired when the document's visibilitychange gets fired. * * @since 1.0.0 */ @@ -181,6 +186,35 @@ export interface AppPlugin { listenerFunc: StateChangeListener, ): Promise & PluginListenerHandle; + /** + * Listen for when the app or the activity are paused. + * + * On iOS it's fired when the native [UIApplication.didEnterBackgroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1623071-didenterbackgroundnotification) event gets fired. + * On Android it's fired when the Capacitor's Activity [onPause](https://developer.android.com/reference/android/app/Activity#onPause()) method gets called. + * On Web it's fired when the document's visibilitychange gets fired and document.hidden is true. + * + * @since 4.1.0 + */ + addListener( + eventName: 'pause', + listenerFunc: () => void, + ): Promise & PluginListenerHandle; + + /** + * Listen for when the app or activity are resumed. + * + * On iOS it's fired when the native [UIApplication.willEnterForegroundNotification](https://developer.apple.com/documentation/uikit/uiapplication/1622944-willenterforegroundnotification) event gets fired. + * On Android it's fired when the Capacitor's Activity [onResume](https://developer.android.com/reference/android/app/Activity#onResume()) method gets called, + * but only after resume has fired first. + * On Web it's fired when the document's visibilitychange gets fired and document.hidden is false. + * + * @since 4.1.0 + */ + addListener( + eventName: 'resume', + listenerFunc: () => void, + ): Promise & PluginListenerHandle; + /** * Listen for url open events for the app. This handles both custom URL scheme links as well * as URLs your app handles (Universal Links on iOS and App Links on Android) diff --git a/app/src/web.ts b/app/src/web.ts index c0ba37dbe..1db1ff356 100644 --- a/app/src/web.ts +++ b/app/src/web.ts @@ -38,5 +38,10 @@ export class AppWeb extends WebPlugin implements AppPlugin { }; this.notifyListeners('appStateChange', data); + if (document.hidden) { + this.notifyListeners('pause', null); + } else { + this.notifyListeners('resume', null); + } }; }