You can look at how firefox implement the Long Back Press.
https://github.com/mozilla-mobile/fenix/blob/master/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
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)
}