集成完成总结.md 16 KB

Kiosk 模式自动启动 - 集成完成总结

📋 任务完成情况

核心目标达成:在 UniApp 离线 Android 工程中,实现 Kiosk 模式功能(禁用锁屏、防退出等)无需通过 JS 调用,应用启动时自动激活。

🎯 实现方案

核心思路

通过自定义 Application 类继承 DCloudApplication,在应用启动时注册 ActivityLifecycleCallbacks,当主 Activity (PandoraEntry/PandoraEntryActivity) 创建时,自动调用 KioskHelper.disableLockScreen()KioskManager.attach()

关键技术点

  1. ActivityLifecycleCallbacks - 监听所有 Activity 生命周期
  2. DevicePolicyManager - Device Owner 模式控制锁屏和 LockTask
  3. WindowManager.LayoutParams - 屏幕常亮、解锁屏幕
  4. 自动化流程 - 无需 JS 调用,原生层自动处理

📂 文件修改清单

✅ 新增文件(7 个)

1. Java 源文件(2 个)

app/src/main/java/com/YuyeTech/HeartRate/
├── MyApplication.java          # 自定义 Application,实现自动初始化
└── KioskHelper.java            # 锁屏控制辅助类

2. 资源文件(1 个)

app/src/main/res/xml/
└── device_admin.xml            # Device Admin 策略配置

3. 文档文件(4 个)

项目根目录/
├── README_KIOSK_INTEGRATION.md  # 集成方案总览
├── KIOSK_SETUP_GUIDE.md         # 详细配置指南
├── QUICK_TEST_GUIDE.md          # 快速测试指南(无需 Device Owner)
├── PROJECT_STRUCTURE.md         # 项目结构说明
├── 快速开始.md                   # 快速开始指南
└── 集成完成总结.md               # 本文件

✏️ 修改文件(1 个)

app/src/main/AndroidManifest.xml

修改内容:
1. Application 改为 com.YuyeTech.HeartRate.MyApplication
2. 添加 4 个权限:DISABLE_KEYGUARD, SYSTEM_ALERT_WINDOW, RECEIVE_BOOT_COMPLETED, FOREGROUND_SERVICE
3. 添加 KioskDeviceAdminReceiver 声明
4. 添加 BootReceiver 声明

🔍 核心代码详解

1. MyApplication.java - 自动初始化入口

public class MyApplication extends DCloudApplication {
    
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 配置 Kiosk
        LaunchConfig.setLaunchActivity(PandoraEntry.class);
        KioskManager.setDebug(BuildConfig.DEBUG);
        
        // ✅ 核心:注册 Activity 生命周期监听
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            
            @Override
            public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                // 只对主 Activity 进行 Kiosk 绑定
                if (activity instanceof io.dcloud.PandoraEntry || 
                    activity instanceof io.dcloud.PandoraEntryActivity) {
                    
                    // ✅ 这里实现了"无需 JS 调用"
                    KioskHelper.disableLockScreen(activity);    // 禁用锁屏
                    KioskHelper.keepScreenOn(activity);          // 屏幕常亮
                    KioskManager.attach(activity);               // 绑定 Kiosk 管理器
                }
            }
            
            @Override
            public void onActivityResumed(@NonNull Activity activity) {
                if (activity instanceof io.dcloud.PandoraEntry || 
                    activity instanceof io.dcloud.PandoraEntryActivity) {
                    KioskManager.onResume();
                }
            }
            
            @Override
            public void onActivityPaused(@NonNull Activity activity) {
                if (activity instanceof io.dcloud.PandoraEntry || 
                    activity instanceof io.dcloud.PandoraEntryActivity) {
                    KioskManager.onPause();
                }
            }
            
            @Override
            public void onActivityDestroyed(@NonNull Activity activity) {
                if (activity instanceof io.dcloud.PandoraEntry || 
                    activity instanceof io.dcloud.PandoraEntryActivity) {
                    KioskManager.onDestroy();
                }
            }
        });
    }
}

关键点

  • 继承 DCloudApplication 保持 UniApp 功能
  • onCreate() 中注册全局 Activity 生命周期监听
  • 判断 Activity 类型,只对主 Activity 执行 Kiosk 初始化
  • 自动处理所有生命周期回调

2. KioskHelper.java - 锁屏控制工具

public class KioskHelper {
    
    /**
     * 禁用锁屏和解锁屏幕
     */
    public static void disableLockScreen(Activity activity) {
        try {
            // 1️⃣ 解锁屏幕(如果当前是锁定状态)
            activity.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            );
            
            // 2️⃣ 作为 Device Owner 禁用锁屏
            DevicePolicyManager dpm = (DevicePolicyManager) 
                activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
            ComponentName adminComponent = new ComponentName(
                activity, 
                KioskDeviceAdminReceiver.class
            );
            
            if (dpm != null && dpm.isDeviceOwnerApp(activity.getPackageName())) {
                // 禁用键盘锁(锁屏)
                dpm.setKeyguardDisabled(adminComponent, true);
                Log.d(TAG, "✅ 锁屏已禁用");
            } else {
                Log.w(TAG, "⚠️ 不是 Device Owner,无法禁用锁屏");
            }
            
        } catch (Exception e) {
            Log.e(TAG, "禁用锁屏失败", e);
        }
    }
    
    /**
     * 保持屏幕常亮
     */
    public static void keepScreenOn(Activity activity) {
        try {
            activity.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            );
            Log.d(TAG, "✅ 屏幕保持常亮");
        } catch (Exception e) {
            Log.e(TAG, "设置屏幕常亮失败", e);
        }
    }
}

关键点

  • 提供静态方法,便于调用
  • 分离锁屏禁用和屏幕常亮逻辑
  • 兼容 Device Owner 和非 Device Owner 模式
  • 详细的日志输出便于调试

3. AndroidManifest.xml - 配置清单

<!-- 1️⃣ 修改 Application -->
<application
    android:name="com.YuyeTech.HeartRate.MyApplication"  <!-- ✅ 改这里 -->
    ...>

<!-- 2️⃣ 添加权限 -->
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- 3️⃣ 添加 Device Admin Receiver -->
<receiver
    android:name="com.ble.mylockview.admin.KioskDeviceAdminReceiver"
    android:permission="android.permission.BIND_DEVICE_ADMIN"
    android:exported="true">
    <meta-data
        android:name="android.app.device_admin"
        android:resource="@xml/device_admin" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>

<!-- 4️⃣ 添加开机启动 Receiver -->
<receiver
    android:name="com.ble.mylockview.boot.BootReceiver"
    android:enabled="true"
    android:exported="true"
    android:directBootAware="true">
    <intent-filter android:priority="1000">
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    </intent-filter>
</receiver>

🔄 执行流程图

┌─────────────────────────────────────────────────────────────┐
│                    应用启动流程                              │
└─────────────────────────────────────────────────────────────┘
                            ↓
                   System Boot / User Launch
                            ↓
┌─────────────────────────────────────────────────────────────┐
│  MyApplication.onCreate()                                   │
│  ├─ LaunchConfig.setLaunchActivity()                        │
│  ├─ KioskManager.setDebug()                                 │
│  └─ registerActivityLifecycleCallbacks()  ← ✅ 关键步骤     │
└─────────────────────────────────────────────────────────────┘
                            ↓
                   PandoraEntry.onCreate()
                            ↓
┌─────────────────────────────────────────────────────────────┐
│  ActivityLifecycleCallbacks.onActivityCreated()             │
│  ├─ 判断:是否为 PandoraEntry/PandoraEntryActivity?         │
│  └─ 是 ✅                                                    │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│  自动执行(无需 JS 调用)                                    │
│  ├─ KioskHelper.disableLockScreen(activity)                 │
│  │   ├─ 添加 FLAG_DISMISS_KEYGUARD                          │
│  │   ├─ 添加 FLAG_SHOW_WHEN_LOCKED                          │
│  │   ├─ 添加 FLAG_TURN_SCREEN_ON                            │
│  │   └─ dpm.setKeyguardDisabled(true)  ← Device Owner 需要  │
│  │                                                           │
│  ├─ KioskHelper.keepScreenOn(activity)                      │
│  │   └─ 添加 FLAG_KEEP_SCREEN_ON                            │
│  │                                                           │
│  └─ KioskManager.attach(activity)                           │
│      ├─ hideSystemUI()           (隐藏状态栏、导航栏)        │
│      ├─ setupSystemUIListener()  (监听系统 UI 变化)          │
│      └─ enableLockTask()         (启用 LockTask 模式)        │
└─────────────────────────────────────────────────────────────┘
                            ↓
                  ✅ Kiosk 模式已激活

📊 功能对比表

功能项 实现方式 Device Owner 需求 JS 调用需求
自动初始化 MyApplication ❌ 否 ❌ 否
屏幕常亮 FLAG_KEEP_SCREEN_ON ❌ 否 ❌ 否
解锁屏幕 FLAG_DISMISS_KEYGUARD ❌ 否 ❌ 否
禁用锁屏 setKeyguardDisabled() ✅ 是 ❌ 否
LockTask 模式 startLockTask() ✅ 是 ❌ 否
全屏沉浸 SYSTEM_UI_FLAG ❌ 否 ❌ 否
拦截按键 onKeyDown() ❌ 否 ❌ 否
五指逃生门 onTouchEvent() ❌ 否 ❌ 否
开机自启动 BootReceiver ❌ 否 ❌ 否

核心优势:✅ 所有功能都无需 JS 调用,完全在原生层自动处理!

🎯 测试验证

基础测试(无需 Device Owner)

# 编译安装
gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk

# 查看日志
adb logcat | grep -E "MyApplication|KioskHelper|KioskManager"

# 启动应用
adb shell am start -n com.YuyeTech.HeartRate/io.dcloud.PandoraEntry

期望日志

D MyApplication: Application 初始化
D MyApplication: ✅ 绑定 Kiosk 到: PandoraEntry
D KioskHelper: ✅ 屏幕保持常亮
W KioskHelper: ⚠️ 不是 Device Owner,无法禁用锁屏
D KioskManager: ❌ 非 DeviceOwner,Kiosk 无效(只会提示一次)

完整测试(需要 Device Owner)

# 1. 恢复出厂设置
# 2. 不登录账号
# 3. 安装应用
gradlew assembleRelease
adb install app/build/outputs/apk/release/app-release.apk

# 4. 设置 Device Owner
adb shell dpm set-device-owner com.YuyeTech.HeartRate/com.ble.mylockview.admin.KioskDeviceAdminReceiver

# 5. 验证
adb shell dumpsys device_policy | grep "Device Owner"

# 6. 查看日志
adb logcat | grep -E "MyApplication|KioskHelper|KioskManager"

期望日志

D MyApplication: Application 初始化
D MyApplication: ✅ 绑定 Kiosk 到: PandoraEntry
D KioskHelper: ✅ 锁屏已禁用
D KioskHelper: ✅ 屏幕保持常亮
D KioskManager: ✅ LockTask 启用(一次)

📚 文档说明

文档名称 用途 适用场景
快速开始.md 快速上手指南 第一次使用
README_KIOSK_INTEGRATION.md 集成方案总览 了解整体架构
KIOSK_SETUP_GUIDE.md 详细配置指南 生产环境部署
QUICK_TEST_GUIDE.md 快速测试指南 开发环境测试
PROJECT_STRUCTURE.md 项目结构说明 理解代码组织
集成完成总结.md 本文档 了解改动内容

🔒 安全建议

1. 修改默认密码

文件myLockView/src/main/java/com/ble/mylockview/admin/KioskManager.java 位置:第 55 行

private static final String ADMIN_PASSWORD = "9527"; // ← 改成你的密码

2. 生产环境配置

// MyApplication.java
KioskManager.setDebug(false);  // ← 关闭 Debug 模式

3. 管理员退出方式

  • 运维人员:5 指长按 5 秒 → 输入密码
  • 开发人员adb shell am task lock stop
  • 应急方案adb shell dpm remove-active-admin ...

🎉 集成完成

✅ 已实现功能

  1. ✅ 应用启动时自动禁用锁屏(Device Owner 模式)
  2. ✅ 应用启动时自动启用屏幕常亮
  3. ✅ 应用启动时自动进入 Kiosk 模式(LockTask)
  4. ✅ 全屏沉浸式界面(隐藏状态栏、导航栏)
  5. ✅ 拦截 Home、Back 等按键
  6. ✅ 五指长按 5 秒 + 密码退出机制
  7. ✅ 开机自动启动应用
  8. 无需在 JS 中调用任何代码

📦 依赖的模块

  • myLockView - Kiosk 模式核心实现
  • myWIFIView - WiFi 配置(需 JS 调用)
  • UniApp DCloud 框架

🚀 后续使用

开发者无需关心 Kiosk 的启动,只需:

  1. 正常开发 UniApp 功能
  2. 需要退出 Kiosk 时:5 指长按 5 秒 + 密码 9527
  3. 如需禁用 Kiosk:在 MyApplication.java 中注释掉相关代码

🔧 自定义选项

  • 修改管理员密码:KioskManager.java 第 55 行
  • 修改逃生门条件:KioskManager.java 第 53-54 行
  • 禁用开机启动:AndroidManifest.xml 中禁用 BootReceiver
  • 调整 Debug 模式:MyApplication.java 第 29 行

📞 技术支持

查看日志

adb logcat -v time | grep -E "KioskManager|MyApplication|KioskHelper"

常用命令

# 退出 Kiosk
adb shell am task lock stop

# 强制停止
adb shell am force-stop com.YuyeTech.HeartRate

# 移除 Device Owner
adb shell dpm remove-active-admin com.YuyeTech.HeartRate/com.ble.mylockview.admin.KioskDeviceAdminReceiver

问题排查

  1. 检查日志是否有 "✅ 绑定 Kiosk 到: PandoraEntry"
  2. 检查 AndroidManifest.xml 中 Application 是否正确
  3. 检查是否设置为 Device Owner
  4. 参考 KIOSK_SETUP_GUIDE.md 故障排查章节

🎊 总结

通过本次集成:

  • ✅ 实现了 Kiosk 模式的零 JS 调用自动启动
  • ✅ 保持了 UniApp 原有功能完整性
  • ✅ 提供了完善的文档和测试指南
  • ✅ 支持 Debug 和 Release 两种模式
  • ✅ 兼容 Device Owner 和非 Device Owner 场景

集成时间:2026-01-22
适用版本:UniApp 离线打包 + Android 8.0+
核心价值:🚀 无需 JS 调用,应用启动自动进入 Kiosk 模式!


祝使用愉快! 🎉