mirror of
https://github.com/apache/cordova-android.git
synced 2026-05-11 00:00:05 +08:00
fix: overwritten backbutton not firing on first time by hardware button and never on back gesture (#1910)
- When pressing the back button after the app starts nothing happens. When navigating to another page, the back button js event starts to fire. - On Android versions, which support the back gesture, nothing happens - This was due to the empty `OnBackPressedCallback.handleOnBackPressed` method, which has to forward its call to `cordova.getActivity().getOnBackPressedDispatcher().onBackPressed()`, but has to disable during this call the `backCallback`. - Generated-By: GPT-5.4, GitHub Copilot Chat - warning about back button override on the right * chore: resolve methods `registerBackPressedCallback` and `unregisterBackPressedCallback`` - The code moved to inline code
This commit is contained in:
@@ -29,6 +29,7 @@ import android.content.BroadcastReceiver;
|
||||
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;
|
||||
@@ -253,7 +254,6 @@ public class CoreAndroid extends CordovaPlugin {
|
||||
* @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;
|
||||
}
|
||||
@@ -263,15 +263,24 @@ public class CoreAndroid extends CordovaPlugin {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,29 +290,29 @@ public class CoreAndroid extends CordovaPlugin {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user