mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00
feat: new 'background/foreground` events for app
On android `suspend/resume` was not doing what was expected. in particular it was called while showing dialogs
This commit is contained in:
@ -22,6 +22,8 @@ export function hasLaunched(): boolean {
|
|||||||
export const launchEvent = 'launch';
|
export const launchEvent = 'launch';
|
||||||
export const suspendEvent = 'suspend';
|
export const suspendEvent = 'suspend';
|
||||||
export const displayedEvent = 'displayed';
|
export const displayedEvent = 'displayed';
|
||||||
|
export const backgroundEvent = 'background';
|
||||||
|
export const foregroundEvent = 'foreground';
|
||||||
export const resumeEvent = 'resume';
|
export const resumeEvent = 'resume';
|
||||||
export const exitEvent = 'exit';
|
export const exitEvent = 'exit';
|
||||||
export const lowMemoryEvent = 'lowMemory';
|
export const lowMemoryEvent = 'lowMemory';
|
||||||
|
@ -43,6 +43,7 @@ export class AndroidApplication extends Observable implements AndroidApplication
|
|||||||
private _orientation: 'portrait' | 'landscape' | 'unknown';
|
private _orientation: 'portrait' | 'landscape' | 'unknown';
|
||||||
private _systemAppearance: 'light' | 'dark';
|
private _systemAppearance: 'light' | 'dark';
|
||||||
public paused: boolean;
|
public paused: boolean;
|
||||||
|
public backgrounded: boolean;
|
||||||
public nativeApp: android.app.Application;
|
public nativeApp: android.app.Application;
|
||||||
public context: android.content.Context;
|
public context: android.content.Context;
|
||||||
public foregroundActivity: androidx.appcompat.app.AppCompatActivity;
|
public foregroundActivity: androidx.appcompat.app.AppCompatActivity;
|
||||||
@ -334,6 +335,9 @@ function initLifecycleCallbacks() {
|
|||||||
rootView.getViewTreeObserver().addOnGlobalLayoutListener(global.onGlobalLayoutListener);
|
rootView.getViewTreeObserver().addOnGlobalLayoutListener(global.onGlobalLayoutListener);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let activitiesStarted = 0;
|
||||||
|
|
||||||
const lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks(<any>{
|
const lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks(<any>{
|
||||||
onActivityCreated: <any>profile('onActivityCreated', function (activity: androidx.appcompat.app.AppCompatActivity, savedInstanceState: android.os.Bundle) {
|
onActivityCreated: <any>profile('onActivityCreated', function (activity: androidx.appcompat.app.AppCompatActivity, savedInstanceState: android.os.Bundle) {
|
||||||
if (!androidApp.foregroundActivity) {
|
if (!androidApp.foregroundActivity) {
|
||||||
@ -374,7 +378,7 @@ function initLifecycleCallbacks() {
|
|||||||
if ((<any>activity).isNativeScriptActivity) {
|
if ((<any>activity).isNativeScriptActivity) {
|
||||||
androidApp.paused = true;
|
androidApp.paused = true;
|
||||||
appCommon.notify(<ApplicationEventData>{
|
appCommon.notify(<ApplicationEventData>{
|
||||||
eventName: appCommon.suspendEvent,
|
eventName: appCommon.backgroundEvent,
|
||||||
object: androidApp,
|
object: androidApp,
|
||||||
android: activity,
|
android: activity,
|
||||||
});
|
});
|
||||||
@ -407,6 +411,15 @@ function initLifecycleCallbacks() {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
onActivityStarted: <any>profile('onActivityStarted', function (activity: androidx.appcompat.app.AppCompatActivity) {
|
onActivityStarted: <any>profile('onActivityStarted', function (activity: androidx.appcompat.app.AppCompatActivity) {
|
||||||
|
activitiesStarted++;
|
||||||
|
if (activitiesStarted === 1) {
|
||||||
|
androidApp.backgrounded = true;
|
||||||
|
appCommon.notify(<ApplicationEventData>{
|
||||||
|
eventName: appCommon.foregroundEvent,
|
||||||
|
object: androidApp,
|
||||||
|
android: activity,
|
||||||
|
});
|
||||||
|
}
|
||||||
androidApp.notify(<AndroidActivityEventData>{
|
androidApp.notify(<AndroidActivityEventData>{
|
||||||
eventName: ActivityStarted,
|
eventName: ActivityStarted,
|
||||||
object: androidApp,
|
object: androidApp,
|
||||||
@ -415,6 +428,15 @@ function initLifecycleCallbacks() {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
onActivityStopped: <any>profile('onActivityStopped', function (activity: androidx.appcompat.app.AppCompatActivity) {
|
onActivityStopped: <any>profile('onActivityStopped', function (activity: androidx.appcompat.app.AppCompatActivity) {
|
||||||
|
activitiesStarted--;
|
||||||
|
if (activitiesStarted === 0) {
|
||||||
|
androidApp.backgrounded = true;
|
||||||
|
appCommon.notify(<ApplicationEventData>{
|
||||||
|
eventName: appCommon.backgroundEvent,
|
||||||
|
object: androidApp,
|
||||||
|
android: activity,
|
||||||
|
});
|
||||||
|
}
|
||||||
androidApp.notify(<AndroidActivityEventData>{
|
androidApp.notify(<AndroidActivityEventData>{
|
||||||
eventName: ActivityStopped,
|
eventName: ActivityStopped,
|
||||||
object: androidApp,
|
object: androidApp,
|
||||||
|
15
packages/core/application/index.d.ts
vendored
15
packages/core/application/index.d.ts
vendored
@ -34,6 +34,16 @@ export const suspendEvent: string;
|
|||||||
*/
|
*/
|
||||||
export const resumeEvent: string;
|
export const resumeEvent: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String value used when hooking to foreground event.
|
||||||
|
*/
|
||||||
|
export const foregroundEvent: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String value used when hooking to background event.
|
||||||
|
*/
|
||||||
|
export const backgroundEvent: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String value used when hooking to exit event.
|
* String value used when hooking to exit event.
|
||||||
*/
|
*/
|
||||||
@ -503,6 +513,11 @@ export class AndroidApplication extends Observable {
|
|||||||
*/
|
*/
|
||||||
paused: boolean;
|
paused: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the main application activity is in background, false otherwise.
|
||||||
|
*/
|
||||||
|
backgrounded: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialized the android-specific application object with the native android.app.Application instance.
|
* Initialized the android-specific application object with the native android.app.Application instance.
|
||||||
* This is useful when creating custom application types.
|
* This is useful when creating custom application types.
|
||||||
|
@ -4,7 +4,7 @@ import { ApplicationEventData, CssChangedEventData, LaunchEventData, LoadAppCSSE
|
|||||||
|
|
||||||
// TODO: explain why we need to this or remov it
|
// TODO: explain why we need to this or remov it
|
||||||
// Use requires to ensure order of imports is maintained
|
// Use requires to ensure order of imports is maintained
|
||||||
const { displayedEvent, exitEvent, getCssFileName, launchEvent, livesync, lowMemoryEvent, notify, on, orientationChanged, orientationChangedEvent, resumeEvent, setApplication, suspendEvent, systemAppearanceChanged, systemAppearanceChangedEvent } = require('./application-common');
|
const { backgroundEvent, displayedEvent, exitEvent, foregroundEvent, getCssFileName, launchEvent, livesync, lowMemoryEvent, notify, on, orientationChanged, orientationChangedEvent, resumeEvent, setApplication, suspendEvent, systemAppearanceChanged, systemAppearanceChangedEvent } = require('./application-common');
|
||||||
// First reexport so that app module is initialized.
|
// First reexport so that app module is initialized.
|
||||||
export * from './application-common';
|
export * from './application-common';
|
||||||
|
|
||||||
@ -220,6 +220,7 @@ export class iOSApplication implements iOSApplicationDefinition {
|
|||||||
const ios = UIApplication.sharedApplication;
|
const ios = UIApplication.sharedApplication;
|
||||||
const object = this;
|
const object = this;
|
||||||
notify(<ApplicationEventData>{ eventName: resumeEvent, object, ios });
|
notify(<ApplicationEventData>{ eventName: resumeEvent, object, ios });
|
||||||
|
notify(<ApplicationEventData>{ eventName: foregroundEvent, object, ios });
|
||||||
const rootView = this._rootView;
|
const rootView = this._rootView;
|
||||||
if (rootView && !rootView.isLoaded) {
|
if (rootView && !rootView.isLoaded) {
|
||||||
rootView.callLoaded();
|
rootView.callLoaded();
|
||||||
@ -227,11 +228,10 @@ export class iOSApplication implements iOSApplicationDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private didEnterBackground(notification: NSNotification) {
|
private didEnterBackground(notification: NSNotification) {
|
||||||
notify(<ApplicationEventData>{
|
const ios = UIApplication.sharedApplication;
|
||||||
eventName: suspendEvent,
|
const object = this;
|
||||||
object: this,
|
notify(<ApplicationEventData>{ eventName: suspendEvent, object, ios });
|
||||||
ios: UIApplication.sharedApplication,
|
notify(<ApplicationEventData>{ eventName: backgroundEvent, object, ios });
|
||||||
});
|
|
||||||
const rootView = this._rootView;
|
const rootView = this._rootView;
|
||||||
if (rootView && rootView.isLoaded) {
|
if (rootView && rootView.isLoaded) {
|
||||||
rootView.callUnloaded();
|
rootView.callUnloaded();
|
||||||
|
Reference in New Issue
Block a user