Reputation: 992
I want to add a listener for when the android system back button is long pressed i.e. a long press version of Activity.onBackPressed
This only needs to work when my app is visible.
Chrome shows the history menu when back is long pressed so it must be possible but can't find a hook for it. Thanks
Upvotes: 0
Views: 3904
Reputation: 567
Add an implementation of the chromium project.
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Detecting a long press of the back button via onLongPress is broken in Android N.
// To work around this, use a postDelayed, which is supported in all versions.
if (keyCode == KeyEvent.KEYCODE_BACK) {
mHandler.postDelayed(mShowHistoryRunnable, ViewConfiguration.getLongPressTimeout());
return super.onKeyDown(keyCode, event);
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mHandler.removeCallbacks(mShowHistoryRunnable);
}
return super.onKeyUp(keyCode, event);
}
Upvotes: 0
Reputation: 13545
You can look at how firefox implement the Long Back Press.
they implement it using both onKeyDown/onKeyUp and onKeyLongPress.
the reason both are used is because
Android N and Huawei devices have broken onKeyLongPress events for the back button, so we instead implement the long press behavior ourselves
- For short presses, we cancel the callback in onKeyUp
- For long presses, the normal keyPress is marked as cancelled, hence won't be handled elsewhere (but Android still provides the haptic feedback), and the long press action is run
Below is their implementation.
// See onKeyDown for why this is necessary
private var backLongPressJob: Job? = null
private fun shouldUseCustomBackLongPress(): Boolean {
val isAndroidN =
Build.VERSION.SDK_INT == Build.VERSION_CODES.N || Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1
// Huawei devices seem to have problems with onKeyLongPress
// See https://github.com/mozilla-mobile/fenix/issues/13498
val isHuawei = Build.MANUFACTURER.equals("huawei", ignoreCase = true)
return isAndroidN || isHuawei
}
private fun handleBackLongPress(): Boolean {
supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach {
if (it is OnBackLongPressedListener && it.onBackLongPressed()) {
return true
}
}
return false
}
final override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
// Inspired by https://searchfox.org/mozilla-esr68/source/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java#584-613
// Android N and Huawei devices have broken onKeyLongPress events for the back button, so we
// instead implement the long press behavior ourselves
// - For short presses, we cancel the callback in onKeyUp
// - For long presses, the normal keypress is marked as cancelled, hence won't be handled elsewhere
// (but Android still provides the haptic feedback), and the long press action is run
if (shouldUseCustomBackLongPress() && keyCode == KeyEvent.KEYCODE_BACK) {
backLongPressJob = lifecycleScope.launch {
delay(ViewConfiguration.getLongPressTimeout().toLong())
handleBackLongPress()
}
}
return super.onKeyDown(keyCode, event)
}
final override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
if (shouldUseCustomBackLongPress() && keyCode == KeyEvent.KEYCODE_BACK) {
backLongPressJob?.cancel()
}
return super.onKeyUp(keyCode, event)
}
final override fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean {
// onKeyLongPress is broken in Android N so we don't handle back button long presses here
// for N. The version check ensures we don't handle back button long presses twice.
if (!shouldUseCustomBackLongPress() && keyCode == KeyEvent.KEYCODE_BACK) {
return handleBackLongPress()
}
return super.onKeyLongPress(keyCode, event)
}
Upvotes: 1
Reputation: 31
I hope below idea works!!!
Add below code in your activity
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//This event will be triggered after 1 second.
//In case if you move out of KEYCODE_BACK, onKeyUp event will be triggered and this event will be cancelled
handler.postDelayed(mLongPressed, 1000);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
handler.removeCallbacks(mLongPressed);
return super.onKeyUp(keyCode, event);
}
handler code:
final Handler handler = new Handler();
Runnable mLongPressed = new Runnable() {
public void run() {
Log.i("Activity", "Long press detected").
//Add your code
}
};
Upvotes: 0
Reputation: 763
You can try overriding the onKeyLongPress
method inside your Activity
.
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
System.out.println("Back button long pressed");
return true;
}
return super.onKeyLongPress(keyCode, event);
}
Upvotes: 5