Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions framework/src/org/apache/cordova/CoreAndroid.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Licensed to the Apache Software Foundation (ASF) under one
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.SystemClock;
import android.content.IntentFilter;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
Expand Down Expand Up @@ -253,7 +254,6 @@ public void run() {
* @param override T=override, F=cancel override
*/
public void overrideBackbutton(boolean override) {
LOG.i("App", "WARNING: Back Button Default Behavior will be overridden. The backbutton event will be fired!");
if (cordova.getActivity() == null) {
return;
}
Expand All @@ -263,15 +263,24 @@ public void overrideBackbutton(boolean override) {
@Override
public void run() {
if (shouldOverride) {
LOG.i("App", "WARNING: Back Button Default Behavior will be overridden. The backbutton event will be fired!");
synchronized (backButtonHandlerLock) {
if (backCallback == null) {
registerBackPressedCallback();
backCallback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
dispatchBackKeyEvent();
}
};
OnBackPressedDispatcherOwner backPressedDispatcherOwner = cordova.getActivity();
backPressedDispatcherOwner.getOnBackPressedDispatcher().addCallback(backPressedDispatcherOwner, backCallback);
}
}
} else {
synchronized (backButtonHandlerLock) {
if (backCallback != null) {
unregisterBackPressedCallback();
backCallback.remove();
backCallback = null;
}
}
}
Expand All @@ -281,29 +290,29 @@ public void run() {
});
}

/**
* Registers an AndroidX back callback so Cordova can keep routing back presses through its
* existing key dispatch path across Android versions without directly referencing newer
* platform-only back APIs.
*/
private void registerBackPressedCallback() {
final OnBackPressedDispatcherOwner backPressedDispatcherOwner = this.cordova.getActivity();
private void dispatchBackKeyEvent() {
// Build a synthetic BACK key press (DOWN + UP) and route it through the WebView.
// This lets Cordova's existing key handling fire the JS "backbutton" event.
final long eventTime = SystemClock.uptimeMillis();
final KeyEvent downEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, 0);
final KeyEvent upEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, 0);

backCallback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
// Intentionally empty.
// On modern Android versions, registering a callback keeps back handling
// routed through Cordova's existing key dispatch path.
}
};
final boolean handledDown = webView.getView().dispatchKeyEvent(downEvent);
final boolean handledUp = webView.getView().dispatchKeyEvent(upEvent);

backPressedDispatcherOwner.getOnBackPressedDispatcher().addCallback(backPressedDispatcherOwner, backCallback);
}
// If either event was consumed, Cordova/WebView already handled back behavior.
if (handledDown || handledUp) {
return;
}

private void unregisterBackPressedCallback() {
backCallback.remove();
backCallback = null;
// Otherwise, delegate to Android's default back dispatcher.
// Temporarily disable this callback to avoid recursive re-entry.
backCallback.setEnabled(false);
try {
cordova.getActivity().getOnBackPressedDispatcher().onBackPressed();
} finally {
backCallback.setEnabled(true);
}
}

/**
Expand Down
Loading