在 UniApp 离线 Android 项目中,启用 Kiosk 模式后,当用户在登录页面(主页面)按返回键时,会返回到一个黑屏页面,导致:
UniApp 使用双 Activity 架构:
PandoraEntry (启动页)
↓
启动
↓
PandoraEntryActivity (主页面, LockTask 模式)
当用户按返回键时:
PandoraEntryActivity (主页面)
↓
按返回键
↓
PandoraEntry (启动页) ← 此时已经是空白页面,显示黑屏
↓
显示"无法取消固定屏幕"
完全禁用返回键,防止任何退出操作:
PandoraEntry(启动页)
PandoraEntryActivity(主页面)
系统设置页面(WiFi 设置)
路径: app/src/main/java/com/YuyeTech/HeartRate/BackPressHandler.java
功能:
核心方法:
public static boolean handleBackPress(Activity activity) {
// 处理返回键按下事件
// 返回 true 表示已处理,false 表示继续默认行为
}
路径: app/src/main/java/com/YuyeTech/HeartRate/MyApplication.java
新增功能:
onActivityCreated 中调用 interceptBackPress()setOnKeyListener 拦截按键事件BackPressHandler 处理拦截方法:
private void interceptBackPress(Activity activity) {
activity.getWindow().getDecorView().setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
return BackPressHandler.handleBackPress(activity);
}
return false;
});
}
用户在 PandoraEntryActivity
↓
按返回键
↓
BackPressHandler.handleBackPress()
↓
检测到 PandoraEntryActivity
↓
显示 Toast: "Kiosk 模式已锁定"
↓
返回 true(拦截事件,禁止返回)
↓
应用保持在主页面 ✅
用户在 PandoraEntry
↓
按返回键
↓
BackPressHandler.handleBackPress()
↓
检测到 PandoraEntry
↓
显示 Toast: "Kiosk 模式已锁定"
↓
返回 true(拦截事件,禁止退出)
↓
应用保持锁定 ✅
用户在 WiFi 设置页面
↓
按返回键
↓
BackPressHandler.handleBackPress()
↓
检测到系统设置页面
↓
返回 false(允许返回)
↓
正常返回到应用主页面 ✅
主页面 → 按返回键 → 黑屏页面 → "无法取消固定屏幕" → 卡住 ❌
主页面 → 按返回键 → Toast: "Kiosk 模式已锁定" → 保持在主页面 ✅
WiFi 设置 → 按返回键 → 正常返回到主页面 ✅
运行 测试返回键功能.bat:
.\测试返回键功能.bat
D BackPressHandler: 🔙 检测到返回键按下
D BackPressHandler: ⛔ PandoraEntryActivity 按返回键 → 已禁用(Kiosk 模式)
D BackPressHandler: 🔙 检测到返回键按下
D BackPressHandler: ⛔ PandoraEntry 按返回键 → 已禁用(Kiosk 模式)
D BackPressHandler: 🔙 检测到返回键按下
D BackPressHandler: ✅ 系统设置页面 按返回键 → 允许返回
adb logcat -s BackPressHandler:D MyApplication:D
在 BackPressHandler.java 中:
showToast(activity, "Kiosk 模式已锁定"); // ← 修改提示文本
如果需要允许其他应用(如浏览器)的返回键,修改 isSettingsActivity() 方法:
private static boolean isSettingsActivity(Activity activity) {
String className = activity.getClass().getName();
return className.startsWith("com.android.settings") ||
className.startsWith("android.settings") ||
className.contains("Settings") ||
className.contains("Browser"); // ← 添加浏览器
}
临时禁用返回键拦截:
// 在 MyApplication.java 中注释掉这行
// interceptBackPress(activity);
使用 View.OnKeyListener 拦截按键事件:
activity.getWindow().getDecorView().setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
return BackPressHandler.handleBackPress(activity);
}
return false;
});
优点:
onBackPressed() 方法ACTION_UP?event.getAction() == KeyEvent.ACTION_UP
ACTION_DOWN: 按键按下时触发ACTION_UP: 按键松开时触发 ← 我们使用这个原因: 避免长按返回键时重复触发
public static boolean handleBackPress(Activity activity) {
// 返回 true = 拦截事件,禁止返回
// 返回 false = 允许默认行为,可以返回
}
Kiosk 模式下的策略:
true(禁止返回)false(允许返回)可能原因:
排查步骤:
查看日志是否有 "返回键拦截器已安装" 消息
adb logcat -s MyApplication:D | findstr "拦截器"
检查是否有 "检测到返回键按下" 日志
adb logcat -s BackPressHandler:D
可能原因:
true排查步骤:
true(拦截成功)onBackPressed() 重写可能原因:
排查步骤:
查看日志中的 Activity 类名
adb logcat -s BackPressHandler:D | findstr "按返回键"
修改 isSettingsActivity() 方法,添加更多判断条件
可能原因:
解决方案:
| 文件 | 说明 |
|---|---|
BackPressHandler.java |
返回键处理器 |
MyApplication.java |
Application 类(已修改) |
测试返回键功能.bat |
自动化测试脚本 |
返回键功能说明.md |
本文档 |
保持双击退出逻辑
使用 moveTaskToBack()
finish() 更优雅记录详细日志
处理异常情况
✅ 问题已解决:
✅ 实现方式:
OnKeyListener 拦截返回键✅ 用户体验: