slambb 1787ea999a Initial commit: Android HeartRate project 2 주 전
..
build 1787ea999a Initial commit: Android HeartRate project 2 주 전
release 1787ea999a Initial commit: Android HeartRate project 2 주 전
src 1787ea999a Initial commit: Android HeartRate project 2 주 전
IMPLEMENTATION_SUMMARY.md 1787ea999a Initial commit: Android HeartRate project 2 주 전
README.md 1787ea999a Initial commit: Android HeartRate project 2 주 전
build.gradle 1787ea999a Initial commit: Android HeartRate project 2 주 전
proguard-rules.pro 1787ea999a Initial commit: Android HeartRate project 2 주 전
内存分配问题修复说明.md 1787ea999a Initial commit: Android HeartRate project 2 주 전
资源释放机制说明.md 1787ea999a Initial commit: Android HeartRate project 2 주 전

README.md

UpdateHelper 更新助手模块

概述

UpdateHelper 是一个独立的 Android 应用模块,专门用于在 Kiosk(固定屏幕)模式下安全地安装 APK 更新包。它解决了主应用在安装自身更新时遇到的 "Package is frozen" 错误。

方案优势

核心问题

当主应用尝试安装自身更新时,Android 8.x 会在安装过程中冻结当前包,导致:

  • 安装结果回调无法启动主应用进程
  • 出现 SecurityException: Package ... is currently frozen! 错误

解决方案

通过 UpdateHelper 配合固定屏幕功能,实现以下闭环逻辑:

  1. 解除固定并跳转:主应用检测到更新后,首先调用 stopLockTask() 解除当前的固定状态,然后通过 Intent 启动 UpdateHelper
  2. Helper 接管显示:UpdateHelper 启动后立即调用 startLockTask() 将自己固定在屏幕上。这样在主应用安装期间,屏幕依然处于锁定状态,用户无法退出到系统桌面
  3. 执行安装:UpdateHelper 在其固定的界面下启动安装进程。使用 PackageInstaller.SessionCallback 实时获取安装进度并显示在 Helper 界面上
  4. 自动恢复
    • 重启后自启:主应用可以注册 ACTION_MY_PACKAGE_REPLACED 广播。当主应用更新完成并重启后,该广播会触发主应用启动
    • Helper 引导:由 UpdateHelper 监听安装完成状态,安装成功后解除自身的固定并重新启动主应用

技术要点

固定状态切换

  • 在 Android 8.1 中,非 Device Owner 应用启动固定屏幕需要用户手动确认
  • 如果应用是 Device Owner(设备管理员),则可以静默开启/关闭固定模式
  • UpdateHelper 需要与主应用共享相同的 Device Owner 权限

安装状态监听

  • 在 UpdateHelper 中使用 PackageInstaller API 提交安装任务
  • 通过监听安装 Session,可以精准捕获安装成功、失败或被取消的状态
  • 使用 BroadcastReceiver 接收安装完成通知

防止冻结异常

  • 将更新逻辑移至 UpdateHelper 后,主应用进程可以被完全杀掉进行覆盖安装
  • 从而避开 SecurityException: Package is frozen 错误
  • 因为此时不再有主应用的活动 Activity 试图持有系统资源

模块结构

UpdateHelper/
├── build.gradle                    # 模块构建配置
├── proguard-rules.pro             # ProGuard 混淆规则
├── src/main/
│   ├── AndroidManifest.xml        # 应用清单文件
│   ├── java/com/yuyetech/updatehelper/
│   │   ├── MainActivity.java      # 主 Activity(固定屏幕 + 安装逻辑)
│   │   └── InstallReceiver.java   # 安装完成广播接收器
│   └── res/
│       ├── layout/
│       │   └── activity_main.xml  # 主界面布局(进度显示)
│       ├── values/
│       │   ├── strings.xml        # 字符串资源
│       │   └── themes.xml         # 主题样式
│       └── mipmap/                # 应用图标
└── README.md                      # 本文件

使用方法

1. 在主应用中调用

在主应用的 InstallModule 中,使用新方法 installApkWithUpdateHelper

// 在 uni-app 中调用
const installModule = uni.requireNativePlugin('InstallModule');
installModule.installApkWithUpdateHelper(apkPath, (result) => {
    if (result.success) {
        console.log('已启动更新助手');
    } else {
        console.error('启动失败:', result.message);
    }
});

2. 工作流程

  1. 主应用:检测到更新 → 下载 APK → 调用 installApkWithUpdateHelper
  2. InstallModule:退出 Kiosk → 启动 UpdateHelper(传递 APK 路径和主包名)
  3. UpdateHelper:启用 Kiosk → 显示进度界面 → 执行安装 → 监听完成
  4. 安装完成:UpdateHelper 收到广播 → 退出 Kiosk → 启动主应用

3. Intent 参数

UpdateHelper 通过 Intent 接收以下参数:

  • apk_path (String): APK 文件的完整路径
  • main_package (String): 主应用的包名(用于安装完成后跳转)

4. 权限要求

UpdateHelper 需要以下权限:

  • INSTALL_PACKAGES:安装应用权限(系统级,需要 Device Owner)
  • REQUEST_INSTALL_PACKAGES:请求安装权限(Android 8.0+)
  • READ_EXTERNAL_STORAGE:读取 APK 文件
  • RECEIVE_BOOT_COMPLETED:监听包替换广播

配置要求

Device Owner 设置

UpdateHelper 需要与主应用共享 Device Owner 权限。确保:

  1. 主应用已设置为 Device Owner
  2. UpdateHelper 的包名已添加到 LockTask 允许列表
  3. 两个应用都使用相同的 Device Admin Receiver

依赖关系

UpdateHelper 依赖 myLockView 模块以使用 Kiosk 功能:

dependencies {
    implementation project(':myLockView')
}

注意事项

  1. 包名配置:确保 UpdateHelper 的 applicationId 与主应用不同
  2. 签名要求:UpdateHelper 和主应用可以使用相同或不同的签名
  3. 图标资源:需要添加 ic_launcher 图标文件到 res/mipmap/ 目录
  4. 测试建议:在真实设备上测试,模拟器可能无法完全模拟 Device Owner 行为

故障排查

问题:UpdateHelper 无法启动

  • 检查 UpdateHelper 是否已安装
  • 检查 Intent 的 Action 和 Package 是否正确
  • 查看 Logcat 日志:adb logcat | grep UpdateHelper

问题:无法固定屏幕

  • 确认设备已设置为 Device Owner
  • 检查 myLockView 模块是否正确集成
  • 查看日志确认 startLockTask() 是否成功调用

问题:安装后无法跳回主应用

  • 检查主应用的包名是否正确传递
  • 确认主应用已安装且可启动
  • 查看 InstallReceiver 的日志

开发说明

编译和安装

  1. 同步 Gradle 项目
  2. 构建 UpdateHelper 模块:./gradlew :UpdateHelper:assembleDebug
  3. 安装到设备:adb install UpdateHelper/build/outputs/apk/debug/UpdateHelper-debug.apk

调试

启用详细日志:

adb logcat | grep -E "UpdateHelper|InstallReceiver"

版本历史

  • v1.0 (2026-01-27)
    • 初始版本
    • 实现固定屏幕 + APK 安装功能
    • 支持安装进度显示
    • 支持安装完成后自动跳回主应用