diff --git a/packages/core/references.d.ts b/packages/core/references.d.ts
index db2b50e87e..4300b64aee 100644
--- a/packages/core/references.d.ts
+++ b/packages/core/references.d.ts
@@ -4,7 +4,7 @@
///
///
///
-///
+///
///
///
///
diff --git a/packages/core/ui/core/view/index.android.ts b/packages/core/ui/core/view/index.android.ts
index 74fc92bde6..aa83cfaf64 100644
--- a/packages/core/ui/core/view/index.android.ts
+++ b/packages/core/ui/core/view/index.android.ts
@@ -72,6 +72,51 @@ interface DialogOptions {
dismissCallback: () => void;
}
+let OnBackPressedCallback;
+
+if (SDK_VERSION >= 33) {
+ OnBackPressedCallback = (androidx.activity.OnBackPressedCallback as any).extend({
+ handleOnBackPressed() {
+ console.log('OnBackPressedCallback handleOnBackPressed called');
+ const dialog = this['_dialog']?.get();
+
+ if (!dialog) {
+ // disable the callback and call super to avoid infinite loop
+
+ this.setEnabled(false);
+
+ return;
+ }
+
+ const view = dialog.fragment.owner;
+
+ const args: AndroidActivityBackPressedEventData = {
+ eventName: 'activityBackPressed',
+ object: view,
+ activity: view._context,
+ cancel: false,
+ };
+
+ // Fist fire application.android global event
+ getNativeScriptGlobals().events.notify(args);
+
+ if (args.cancel) {
+ return;
+ }
+
+ view.notify(args);
+
+ if (!args.cancel) {
+ this.setEnabled(false);
+
+ dialog.getOnBackPressedDispatcher().onBackPressed();
+
+ this.setEnabled(true);
+ }
+ },
+ });
+}
+
interface TouchListener {
new (owner: View): android.view.View.OnTouchListener;
}
@@ -121,7 +166,7 @@ function initializeDialogFragment() {
}
@NativeClass
- class DialogImpl extends android.app.Dialog {
+ class DialogImpl extends androidx.appcompat.app.AppCompatDialog {
constructor(
public fragment: DialogFragmentImpl,
context: android.content.Context,
@@ -129,6 +174,16 @@ function initializeDialogFragment() {
) {
super(context, themeResId);
+ if (SDK_VERSION >= 33 && OnBackPressedCallback) {
+ const callback = new OnBackPressedCallback(true);
+
+ callback['_dialog'] = new WeakRef(this);
+
+ // @ts-ignore
+
+ this.getOnBackPressedDispatcher().addCallback(this, callback);
+ }
+
return global.__native(this);
}
@@ -138,6 +193,10 @@ function initializeDialogFragment() {
}
public onBackPressed(): void {
+ if (SDK_VERSION >= 33) {
+ super.onBackPressed();
+ return;
+ }
const view = this.fragment.owner;
const args = {
eventName: 'activityBackPressed',
diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts
index a8838b7e8d..168c81ac52 100644
--- a/packages/core/ui/frame/index.android.ts
+++ b/packages/core/ui/frame/index.android.ts
@@ -17,6 +17,7 @@ import { AndroidActivityBackPressedEventData, AndroidActivityNewIntentEventData,
import { Application } from '../../application/application';
import { isEmbedded, setEmbeddedView } from '../embedding';
import { CALLBACKS, FRAMEID, framesCache, setFragmentCallbacks } from './frame-helper-for-android';
+import { Device } from '../../platform';
export * from './frame-common';
export { setFragmentClass } from './fragment';
@@ -762,6 +763,78 @@ function startActivity(activity: androidx.appcompat.app.AppCompatActivity, frame
activity.startActivity(intent);
}
+let OnBackPressedCallback;
+
+if (parseInt(Device.sdkVersion) >= 33) {
+ OnBackPressedCallback = (androidx.activity.OnBackPressedCallback).extend('com.tns.OnBackPressedCallback', {
+ handleOnBackPressed() {
+ if (Trace.isEnabled()) {
+ Trace.write('NativeScriptActivity.onBackPressed;', Trace.categories.NativeLifecycle);
+ }
+
+ const activity = this['_activity']?.get();
+
+ if (!activity) {
+ if (Trace.isEnabled()) {
+ Trace.write('NativeScriptActivity.onBackPressed; Activity is null, calling super', Trace.categories.NativeLifecycle);
+ }
+
+ this.setEnabled(false);
+
+ return;
+ }
+
+ const args = {
+ eventName: 'activityBackPressed',
+
+ object: Application,
+
+ android: Application.android,
+
+ activity: activity,
+
+ cancel: false,
+ };
+
+ Application.android.notify(args);
+
+ if (args.cancel) {
+ return;
+ }
+
+ const view = activity._rootView;
+
+ let callSuper = false;
+
+ const viewArgs = {
+ eventName: 'activityBackPressed',
+
+ object: view,
+
+ activity: activity,
+
+ cancel: false,
+ };
+
+ view?.notify(viewArgs);
+
+ // In the case of Frame, use this callback only if it was overridden, since the original will cause navigation issues
+
+ if (!viewArgs.cancel && (view?.onBackPressed === Frame.prototype.onBackPressed || !view?.onBackPressed())) {
+ callSuper = view instanceof Frame ? !Frame.goBack() : true;
+ }
+
+ if (callSuper) {
+ this.setEnabled(false);
+
+ activity.getOnBackPressedDispatcher().onBackPressed();
+
+ this.setEnabled(true);
+ }
+ },
+ });
+}
+
const activityRootViewsMap = new Map>();
const ROOT_VIEW_ID_EXTRA = 'com.tns.activity.rootViewId';
@@ -1055,4 +1128,13 @@ export class ActivityCallbacksImplementation implements AndroidActivityCallbacks
export function setActivityCallbacks(activity: androidx.appcompat.app.AppCompatActivity): void {
activity[CALLBACKS] = new ActivityCallbacksImplementation();
+ if (OnBackPressedCallback && !activity['_onBackPressed']) {
+ const callback = new OnBackPressedCallback(true);
+
+ callback['_activity'] = new WeakRef(activity);
+
+ activity['_onBackPressed'] = true;
+
+ (activity as androidx.activity.ComponentActivity).getOnBackPressedDispatcher().addCallback(activity, callback);
+ }
}