更新记录

1.0.0(2026-08-29) 下载此版本

android app版本更新


平台兼容性

uni-app x(5.0)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - -

ff-uni-upgrade

App 版本升级 UTS 插件,封装断点续传、通知栏进度、自动重试、MD5 校验与系统安装等通用能力。

平台支持

平台 实现状态 升级方式
Android ✅ 已实现 APK 整包下载(断点续传 + 自动重试 + 通知栏进度)+ 系统安装
iOS ⚠️ 已声明未实现 暂无实现(package.json 声明 √,源码未提供 utssdk/app-ios/
HarmonyOS ⚠️ 已声明未实现 暂无实现(package.json 声明 √,源码未提供 utssdk/app-harmony/

三端 API 表保持一致:iOS / HarmonyOS 端当前没有任何实现文件,调用本插件在非 Android 平台会因找不到 utssdk/app-ios/index.utsutssdk/app-harmony/index.uts 而编译失败。如需 iOS / HarmonyOS 支持,需自行补充对应平台的 UTS / Swift / ArkTS 实现,或将 package.json 的 uni_modules.client 中对应平台标记为 ×

⚠️ Android 端集成说明(重要)

Android 端下载内核为 MZCretin/AutoUpdateProject(JitPack 依赖 com.github.MZCretin:AutoUpdateProject:v2.0.7,见 utssdk/app-android/config.json)。注意:

  • v2.0.7 是 JitPack 上唯一同时有 AAR 且为 AndroidX 依赖的版本(已实测 v2.0.8 / v2.0.9 / v2.1.0 在 JitPack 上只有 POM 无 AAR;曾尝试的 cretinautoupdatelibrary:* 内部 artifact 不存在,JitPack 直接返回 401 Unauthorized)。升级该库版本前务必先访问 https://jitpack.io/com/github/MZCretin/AutoUpdateProject// 确认 .aar 存在
  • 真机运行 / 云打包必须使用自定义基座:引入三方 gradle 依赖后,标准基座不包含该依赖,需提交云端打包生成自定义基座后方可生效。
  • 需要 HBuilderX 4.36+:config.json 中通过 project.repositories 配置了 JitPack 仓储。
  • 依赖坐标说明:该库 JitPack 上的 POM 不带任何传递依赖(v2.0.7 已实测),故 config.json 中已显式补齐 com.liulishuo.filedownloader:library:1.7.6(断点续传引擎)及 androidx 依赖,请勿删除。
  • FileProvider 冲突风险:AutoUpdateProject 自带 authority 为 ${applicationId}.fileprovider 的 FileProvider。若宿主 App 或其他插件已声明相同 authority,云打包合并 manifest 时会失败,需二选一。

由该库提供的 Android 端能力:

  • 断点续传:下载写入 .temp 临时文件,中断/暂停/杀进程后再次下载自动从断点继续
  • 下载失败自动重试 3 次
  • 通知栏实时下载进度(失败后可点击通知栏重新下载)
  • 相同版本只下载一次:传入 fileSize 时,本地已有完整 APK 直接唤起安装器
  • MD5 校验:传入 md5 时下载完成后校验,校验失败不安装
  • 下载完成后自动唤起系统安装器(Android 8+ 安装权限由本插件前置检查并引导跳转设置页)

Android 权限清单

utssdk/app-android/AndroidManifest.xml 自动合并到宿主 manifest:

权限 用途
android.permission.INTERNET 下载 APK
android.permission.ACCESS_NETWORK_STATE 网络状态
android.permission.REQUEST_INSTALL_PACKAGES Android 8.0+ 安装未知应用
android.permission.POST_NOTIFICATIONS Android 13+ 下载进度通知栏

安装

ff-uni-upgrade 放入项目的 uni_modules/ 目录下,HBuilderX 会自动识别。

使用示例

import {
  checkUpgrade, , onResult,
  offProgress, offResult, dispose,
  getCurrentProgress, resumeDownload
} from '@/uni_modules/ff-uni-upgrade'

// 1. 监听下载进度
((e) => {
  console.log(`下载进度: ${e.percent}% (${e.downloaded}/${e.total})`)
})

// 2. 监听结果
onResult((r) => {
  if (r.status === 'success') {
    console.log('下载完成,安装器已自动唤起')
  } else if (r.status === 'cancel') {
    console.log('用户取消')
  } else {
    console.error('升级失败:', r.error)
  }
})

// 3. 触发升级检查
checkUpgrade({
  version: '1.2.0',
  downloadUrl: 'https://example.com/app-v1.2.0.apk',
  updateContent: '1. 修复已知问题\n2. 优化性能',
  isForceUpdate: false,
  versionCode: 25,       // 可选:传给升级库做版本比对
  fileSize: 31338250,    // 可选:启用"已下载文件完整性校验"
  md5: '68919BF998C29DA3F5BD2C0346281AC0' // 可选:下载完成后 MD5 校验
})

// 4. 主动查询当前进度(无需注册 )
const cur = getCurrentProgress()
if (cur != null) {
  console.log(`当前进度: ${cur.percent}%`)
}

// 5. 主动恢复之前暂停的下载(URL 必须与上次一致)
const resumed = resumeDownload({
  version: '1.2.0',
  downloadUrl: 'https://example.com/app-v1.2.0.apk',
  updateContent: '',
  isForceUpdate: false
})
console.log(resumed ? '续传已触发' : '无断点可恢复')

// 6. 页面卸载时释放资源(重要!)
onUnload(() => {
  dispose()
})

API

checkUpgrade(options: UpgradeOptions, platformConfig?: string): void

触发升级检查并展示弹窗。platformConfig 为三端 API 表占位(Android 端忽略;iOS / HarmonyOS 当前未实现该参数语义)。

参数 UpgradeOptions

  • version: string — 新版本号(显示用,Android 端同时用作 APK 文件名)
  • downloadUrl: string — APK 下载地址(Android 必填;传空字符串会被 resultDispatcher('fail', ...) 上报为参数错误)
  • updateContent: string — 更新内容(支持 \n 换行)
  • isForceUpdate: boolean — 是否强制升级(true 时弹窗的 cancelText 不展示,按返回键 / 点遮罩会再次弹出)
  • versionCode?: number — 新版本 versionCode(可选,Android 端传给升级库做版本比对)
  • fileSize?: number — APK 总字节数(可选,Android 端启用已下载文件完整性校验)
  • md5?: string — APK 文件 MD5(可选,Android 端下载完成后校验,失败不安装)

onProgress(callback): void

注册下载进度回调,回调参数:

  • percent: number — 0-100(服务器未返回总长度时为 -1)
  • downloaded: number — 已下载字节(未传 fileSize 时为 -1)
  • total: number — 总字节(未传 fileSize 时为 -1)

必须用 @UTSJS.keepAlive 标注(本插件已在 Android 实现内标注)—— 跨边界回调若不持有强引用会被 JSCore GC 释放,导致"调一次后失效"。

多次注册会替换前一次。建议在页面 onUnload 中调用 offProgress()dispose() 释放回调引用。

offProgress(): void

注销下载进度回调(与 onProgress 配对)。

onResult(callback): void

注册升级结果回调,回调参数:

  • status: 'success' | 'cancel' | 'fail'
  • error?: string | null — 失败时的错误描述

onProgress回调函数须被 UTS 顶层模块级 var 持有引用才能跨多次触发持续生效。本插件通过 resultCallback 模块级变量持有引用,无需业务方额外处理。

offResult(): void

注销升级结果回调(与 onResult 配对)。

dispose(): void

释放升级插件资源:offProgress() + offResult() + clearResumeCache(),并清空 Kotlin 端 UpgradeCallbacks 的 MD5 失败回调。

建议在页面 onUnloadonBeforeUnmount 中调用,避免:

  1. 路由切换后旧页面的回调仍被触发,错误地修改新页面的响应式状态
  2. 已卸载页面持有的 reactive() 对象被闭包引用,无法被 GC
  3. 用户离开页面但断点文件仍占用存储空间

cancelUpgrade(): void

暂停当前升级流程并保留断点记录(不删除 .temp 半成品文件)。 下次 checkUpgrade 相同 downloadUrl 时自动从断点继续。彻底丢弃下载进度请调用 clearResumeCache()

取消事件由 Kotlin 端 listener.pause() 回调统一上报(通过 onResultstatus: 'cancel'),本方法不直接 dispatch result(避免双重上报)。

getCurrentProgress(): ProgressEvent | null(v2.1.0 新增)

主动查询当前下载进度(无需注册 onProgress)。未启动下载时返回 null

返回 ProgressEvent 字段同 onProgress 回调参数。

适用于:从其他页面返回升级页时刷新进度条;不依赖回调注册的轮询场景。

getResumeInfo(): ResumeInfo | null

查询是否存在未完成的下载(App 重启后可据此提示用户继续)。无未完成下载时返回 null

返回 ResumeInfo

  • url: string — 上次未完成下载的地址
  • fileName: string — APK 文件名
  • downloaded: number — 已下载字节(以 .temp 文件实际大小为准)
  • total: number — 总字节(未知时为 -1)
  • percent: number — 进度百分比 0-100(未知时为 -1)

v2.1.0 的 Kotlin 层 JSON 中新增了 hasResume: boolean 字段用于内部判断;UTS 端 ResumeInfo 类型未导出该字段,调用方判断"是否有断点"直接 != null 即可。

resumeDownload(options: UpgradeOptions): boolean(v2.1.0 新增)

主动恢复之前暂停的下载。URL 必须与上次一致才能续传,否则返回 false。 成功触发后返回 true

clearResumeCache(): void

清除断点续传缓存:删除 .temp 半成品文件、已下载 APK 与任务记录(Kotlin 端用 AppUpdateUtils.clearAllData() + FileDownloadUtils.deleteTargetFile / deleteTempFile 兜底,库清理失败时也能彻底删除)。

installDownloaded(): void

安装已下载的 APK(Android 端)。正常流程下下载完成后升级库会自动唤起系统安装器,本方法用于安装被取消或"安装未知应用"权限授权后重试的场景。Android 8+ 未授予权限时会跳转系统设置页。

v2.1.0 强化:进程被杀后 currentFilePath 内存值丢失,本方法会自动从以下 3 级回退重建路径:

  1. 内存 currentFilePath(运行时缓存)
  2. SharedPreferences KEY_FILE_PATHdownloadComplete()commit() 原子化写入)
  3. AppUtils.getAppLocalPath(versionName)(按 versionName 重新计算路径;若找到会同步写回 SharedPreferences)

保证"下载完成后被杀进程"也能继续安装。

Android 下载实现说明

Android 端基于 AutoUpdateProject(见 utssdk/app-android/UpgradeNative.kt 的薄封装):

  • 下载引擎为库内置的 filedownloader:断点续传(.temp 文件 + Range 请求)、失败自动重试 3 次
  • 下载进度实时显示在通知栏(Android 13+ 需通知权限,失败后可点击通知栏重新下载)
  • APK 存储路径为应用专属缓存目录 Android/data/<pkg>/cache/<pkg>/apks/<应用名>_<版本号>.apk
  • 下载完成后自动唤起系统安装器;传入 md5 时先校验 MD5,校验失败不安装
  • Android 8+ 的"安装未知应用"权限下载开始前前置检查并引导跳转设置页(库内安装逻辑未做此检查,由本插件补齐;installDownloaded() 内同样检查)
  • 暂停 / 出错 / 杀进程均保留断点,App 重启后 getResumeInfo() 可感知,再次触发升级自动续传

v2.1.0 重构

  • UTS 端删除 setInterval 轮询:Kotlin 端 AppDownloadListener 通过模块级分发器(progressDispatcher / resultDispatcher / md5FailDispatcher直接回调到 UTS。分发器由 UTS 模块级 var 持有引用避免被 GC;onProgress / onResult 函数用 @UTSJS.keepAlive 标注保护 callback 参数。
  • 回调在主线程上派发(Handler(Looper.getMainLooper()).post),避免子线程修改 UTS 响应式状态时静默失败。
  • 状态机单一来源:Kotlin 端用 UpgradeStatus enum(Idle / Downloading / Paused / Completed / Error)替代 5 个 STATUS_xxx 常量,UTS 端不再做状态判定。
  • 错误码集中:Kotlin 端用 UpgradeErrorCode enum 维护(NETWORK=1001 / DOWNLOAD=1002 / INSTALL=1003 / PARAMS=1004 / NOT_SUPPORTED=1005 / CANCEL=1006 / PERMISSION_DENIED=1007);UTS 端通过 UPGRADE_ERR_xxx 常量导出公共契约。
  • SharedPreferences 任务边界写入用 commit() 而非 apply()(URL / versionName / fileSize 三个字段原子化)。
  • installDownloaded 自愈:3 级回退(内存 → SharedPreferences → AppUtils.getAppLocalPath)。
  • 取消上报单一来源:cancelUpgrade() 仅调 UpgradeNative.pauseDownload(),由 Kotlin 端 listener.pause() 通过 onResultstatus: 'cancel' 统一上报(v2.0.0 的双源上报已修复)。

错误码

错误码在 Kotlin 端集中在 UpgradeErrorCode enum 中维护,UTS 端通过 UPGRADE_ERR_xxx 常量导出公共契约(utssdk/interface.uts):

错误码 常量名 含义 触发场景
1001 UPGRADE_ERR_NETWORK 网络异常 网络不通 / DNS 解析失败 / 下载过程断网
1002 UPGRADE_ERR_DOWNLOAD 下载失败 库内 filedownloader 重试 3 次后仍失败;MD5 校验不通过
1003 UPGRADE_ERR_INSTALL 安装失败 installApk 抛异常 / 系统安装器返回错误
1004 UPGRADE_ERR_PARAMS 参数错误 downloadUrl 为空 / version 为空 / UpgradeOptions 为 null
1005 UPGRADE_ERR_NOT_SUPPORTED 当前平台不支持 iOS / HarmonyOS 端调用(本插件未实现时)
1006 UPGRADE_ERR_CANCEL 取消升级 用户主动 cancelUpgrade()v2.0.0 起通过 onResult status: 'cancel' 上报,不走此错误码;保留以便业务方按需消费)
1007 UPGRADE_ERR_PERMISSION_DENIED 权限被拒 Android 8+ 未授予"安装未知应用"权限 / 权限检查后用户未授权

v2.1.0 起 onResult 回调的 status 字段已覆盖全部成功 / 取消 / 失败场景;UpgradeError 类(utssdk/unierror.uts)保留供业务方按错误码二次封装。

注意事项

  • 仅 Android 端实现:iOS / HarmonyOS 端当前未提供实现源码,在对应平台调用本插件会编译失败
  • 自定义基座:Android 端引入了 JitPack 三方依赖,真机运行与云打包需使用自定义基座
  • 安装未知应用权限:Android 8.0+ 首次升级会引导用户开启"安装未知应用"权限;用户在设置页授权后需重新触发升级
  • 通知权限:Android 13+ 需授予通知权限才能看到下载进度通知栏(权限已在插件 manifest 中声明,但需业务方在 App 启动时主动申请)
  • 回调清理:务必在 onUnload / onBeforeUnmount 中调用 dispose(),避免已卸载页面的回调继续触发
  • 跨页面共享回调:本插件的模块级变量持有回调引用,所有页面共享同一回调实例。若需要按页面隔离回调,可在使用前 offProgress / offResult 后再 onProgress / onResult

调试与日志

Kotlin 端统一使用 TAG ff-uni-upgrade 输出日志。关键日志点:

  • ensureInit: applicationContext is not Application — 初始化失败,应用上下文不是 Application
  • ensureNativeBridge: ... — 桥接 AppDownloadListener / MD5CheckListener 到库
  • startDownload: url=..., version=..., fileSize=..., md5Check=... — 任务启动
  • clearResumeCache: done — 断点缓存清除完成
  • persistFilePath: ... / installDownloaded: ... — 进程被杀后自愈路径

UTS 端关键日志:

  • [ff-uni-upgrade] MD5 校验失败:期望 xxx,实际 yyy — MD5 不匹配
  • [ff-uni-upgrade] showModal fail: ... — 升级弹窗显示失败

版本

  • 2.1.0(2026-08-28)— Android 端重构:删除 UTS setInterval 轮询,改用 Kotlin→UTS 直接回调(typealias + 单例属性 + 主线程分发 + @UTSJS.keepAlive);installDownloadedcurrentFilePath 丢失(进程被杀)后从 SharedPreferences 自愈;SharedPreferences 任务边界写入 commit() 原子化;状态机单一来源(UpgradeStatus enum);错误码集中(UpgradeErrorCode enum);新增 offProgress / offResult / dispose / getCurrentProgress / resumeDownload API;错误码新增 1007 PERMISSION_DENIED。依赖维持 AutoUpdateProject:v2.0.7(v2.0.8+ 在 JitPack 上无 AAR,cretinautoupdatelibrary:* 内部 artifact 不存在,已实测 JitPack 401 Unauthorized)
  • 2.0.0(2026-08-28)— Android 端重构为集成 AutoUpdateProject(filedownloader 断点续传 + 自动重试 + 通知栏进度 + MD5 校验),UpgradeOptions 新增可选字段 versionCode/fileSize/md5
  • 1.1.0(2026-08-27)— 自实现 Range/If-Range 断点续传,新增 getResumeInfo / clearResumeCache API
  • 1.0.0(2026-08-27)— 初始版本,仅支持 Android 端

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。