Android 长按系统返回键监听

Android long press system back button listener

我想在 android 系统后退按钮被长按时添加一个监听器,即 Activity.onBackPressed

的长按版本

这只需要在我的应用程序可见时工作。

Chrome 长按后退时显示历史菜单,所以它一定是可能的,但找不到它的钩子。谢谢

您可以尝试覆盖 Activity 中的 onKeyLongPress 方法。

@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);
}

希望下面的想法可行!!!

在您的 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);
}

处理程序代码:

final Handler handler = new Handler();
Runnable mLongPressed = new Runnable() {
    public void run() {
        Log.i("Activity", "Long press detected").
       //Add your code
    }
};

你可以看看firefox是如何实现长按后退的。

https://github.com/mozilla-mobile/fenix/blob/master/app/src/main/java/org/mozilla/fenix/HomeActivity.kt

他们使用 onKeyDown/onKeyUp 和 onKeyLongPress 来实现它。

两者都被使用的原因是因为

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

下面是它们的实现。

// 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)
}