# appUpdate **Repository Path**: yos/appUpdate ## Basic Information - **Project Name**: appUpdate - **Description**: 一键检查版本、下载 APK、通知「点击安装」、更新界面(随 Activity 迁移),支持非强制更新的后台下载等行为。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-14 - **Last Updated**: 2026-08-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # appUpdate Kotlin/Android 库:一键检查版本、下载 APK、通知「点击安装」、`DialogFragment` 更新界面(随 Activity 迁移),支持非强制更新的后台下载等行为。 **配套后端:[https://gitee.com/yos/appserver](https://gitee.com/yos/appserver)** 也可以根据json格式,自行实现后端服务 **Maven / Gradle:** ```gradle dependencies { implementation "com.kotlinx:appUpdate:0.0.5" } ``` ```kotlin // build.gradle.kts dependencies { implementation("com.kotlinx:appUpdate:0.0.5") } ``` ![ui](doc/UI.jpg) --- ## 环境要求 | 项 | 说明 | |----|------| | **minSdk** | 23 | | **宿主 Activity** | **`AppCompatActivity`**(内部会当作 `FragmentActivity` 使用) | | **Kotlin** | 推荐使用与库相同或更高版本的 Kotlin 编译器 | | **合并清单** | 库自带权限与 `FileProvider`,随 **`implementation` 合并进宿主** | | **Java** | 库模块按 **Java 17** 编译;宿主宜使用 **17+** 或兼容配置 | --- ## 快速开始 ### 1. 在入口 Activity 发起检查 使用自有更新服务器时,**须先设置 `AppUpdate.baseUrl`**(无默认值、不持久化): ```kotlin AppUpdate.baseUrl = "http://apk.kotlinx.com:9999" // 改成自己的服务器地址 AppUpdate().checkAndUpdate(this) ``` ```java AppUpdate.baseUrl = "http://apk.kotlinx.com:9999"; // 改成自己的服务器地址 new AppUpdate().checkAndUpdate(this); ``` 也可在 `Application.onCreate` 中统一设置 `AppUpdate.baseUrl`。 ### 2. 跳过检查接口,直接弹更新窗 已有 `ApkInfo`(版本号、更新说明、下载地址等)时,**无需配置 `baseUrl`**: ```kotlin val apkInfo = ApkInfo( changelog = "1.新增了XX功能\n2.修复了XX导致的异常", downloadUrl = "http://xxx.xxxx.com/download/xxxx.apk", forceUpdate = false, versionCode = 2, versionName = "0.0.2", ) AppUpdate().launchUpdateActivity(this, apkInfo) ``` ### 3. 接口与行为说明 - **请求地址**:`GET {baseUrl}/appserver/apk/latest?packageName={宿主包名}` - **`checkAndUpdate`**:仅当服务端返回的 **`ApkInfo.versionCode` 大于本地** 时弹出更新弹窗;未设置 `baseUrl` 会失败并提示「未配置更新服务器地址」。 - **`check`**:只拉取最新包信息并回调 **`ApkInfo`**,**不做** 与本地版本比较。 ```kotlin AppUpdate().check(this) { apk -> // 自行处理 apk(versionCode、forceUpdate、downloadUrl、md5、changelog 等) } AppUpdate().check(this, object : CheckUpdateCallback { override fun onSuccess(apk: ApkInfo) { /* ... */ } override fun onFailure(error: CheckUpdateError, message: String) { /* ... */ } }) AppUpdate().checkAndUpdate(this) { error, message -> // 仅失败回调(可选) } ``` ### 4. 取消进行中的「检查更新」网络请求 取消的是 **拉取 `/appserver/apk/latest` 的 OkHttp 请求**,**不会**取消已在进行的 **APK 文件下载**。 ```kotlin AppUpdate().cancelCheck() ``` --- ## 全局配置(可选) 均在 **`AppUpdate` companion** 下;**`baseUrl` 在使用 `check` / `checkAndUpdate` 时必填**,其余须在调用前设置。 | 字段 | 说明 | 默认 | |------|------|------| | **`baseUrl`** | 更新服务器根地址(不含末尾 `/`)。`launchUpdateActivity` 可不设。 | `""` | | **`themeOverlayStyle`** | `R.style.xxx`,通过 `DialogFragment.setStyle` 套在更新弹窗上;`0` 表示使用库内置 `Theme.AppUpdate.Dialog`。 | `0` | | **`keepUpdateDialogOnTopWithinApp`** | 同应用内切换 Activity 时,是否把更新弹窗迁到前台 Activity。 | `true` | | **`openInstallUiImmediatelyAfterDownload`** | 下载完成后是否立刻打开系统安装界面;`false` 时偏重通知 / 弹窗内再点安装。 | `true` | | **`showCheckUpdateErrorToast`** | 检查失败(未配置 baseUrl、网络、HTTP、解析、接口 code)是否 Toast。 | `true` | | **`showDownloadErrorToast`** | 下载失败、校验失败、非 Wi‑Fi 拒绝下载是否 Toast。 | `true` | | **`showInstallErrorToast`** | 安装失败是否 Toast。 | `true` | | **`showLogcatLogs`** | 是否输出 Logcat(检查响应、OkHttp、安装失败等)。 | 随库 **`BuildConfig.DEBUG`** | | **`postponeUpdatePromptHours`** | 非强制更新点「稍后再说」/ 关闭弹窗后,同一 `versionCode` 多少小时内不再自动弹出;**`0` 不限制**。 | `0` | | **`downloadOnWifiOnly`** | 为 `true` 时仅 Wi‑Fi 下允许下载;已有本地缓存包仍可安装。 | `false` | | **`useInstallNotification`** | 下载完成后是否通过通知栏提醒「点击安装」。 | `true` | | **`showNotificationPermissionRationale`** | `useInstallNotification` 为 true 且 Android 13+ 申请通知权限前,是否先弹用途说明。 | `false` | **Java 示例:** ```java AppUpdate.baseUrl = "https://your.api.example"; AppUpdate.showCheckUpdateErrorToast = true; AppUpdate.useInstallNotification = true; new AppUpdate().checkAndUpdate(this); ``` --- ## 服务端 JSON 约定 库使用 **Gson** 解析为 **`UpdateResponse`**: ```json { "code": 0, "msg": "ok", "data": { "versionCode": 101, "versionName": "1.0.1", "downloadUrl": "https://cdn.example/app-release.apk", "changelog": "- 修复与改进", "forceUpdate": false, "md5": "可选;配置后下载完成与命中本地缓存时会做 MD5 校验", "fileSize": 0, "packageName": "" } } ``` - **`code == 0` 且 `data` 非空** 视为成功。 - **`forceUpdate`**:为 `true` 时禁用「稍后再说」类关闭路径(按产品设计走退出或必须更新)。 - **`md5`**:非空时下载完成与命中本地缓存前会做 MD5 校验;**未配置则不校验**,仅要求 APK 文件存在。 HTTP 明文地址时,请配置 **`networkSecurityConfig`** 或改用 **HTTPS**,见下文。 --- ## 主题与品牌色(推荐) 在宿主 `res/values/themes.xml` 中与库 **同名主题** **`Theme.AppUpdate.Dialog`**,`parent` 指向库的 **`Theme.AppUpdate.Base.Dialog`**,再覆盖配色属性: ```xml ``` 可覆盖的属性名:**`appUpdateColorPrimary`、`appUpdateColorPrimaryDark`、`appUpdateColorAccent`、`appUpdateColorOnPrimary`、`appUpdateColorScrim`、`appUpdateColorOutline`**。 --- ## 清单合并说明(宿主无需手写) 库 `AndroidManifest` 中会合并进宿主: | 合并项 | 用途 | |--------|------| | **`INTERNET`** | 检查更新、下载 APK | | **`ACCESS_NETWORK_STATE`** | 判断是否为 Wi‑Fi(配合 **`downloadOnWifiOnly`**) | | **`REQUEST_INSTALL_PACKAGES`** | 安装 APK | | **`POST_NOTIFICATIONS`** | Android 13+ 发「下载完成 / 点击安装」通知(**`useInstallNotification=false` 时不申请**) | | **`AppUpdateFileProvider`** | 独立 `FileProvider`,`authorities="{applicationId}.appupdate.fileprovider"`,路径 **`files/appupdate/`**;与宿主 **`{applicationId}.fileProvider`** 可并存 | --- ## ProGuard / R8 库已附带 **`consumer-rules.pro`**(保留 **`ApkInfo`、`UpdateResponse`、`CheckUpdateCallback`** 等)。宿主开启混淆时一般会随 AAR **自动合并**;若出现异常,再在宿主 **`proguard-rules.pro`** 中按报错补充 `-keep`。 --- ## 常见问题 ### 1. `checkAndUpdate` 无反应? - 是否已设置 **`AppUpdate.baseUrl`**。 - 确认 **`AppCompatActivity`** 且服务端 **`versionCode` 大于本地**。 - 是否被 **`postponeUpdatePromptHours`** 推迟(同一版本在冷却期内不会重复弹窗)。 - 看 Logcat / Toast:未配置 baseUrl、网络失败、HTTP 非 2xx、`code!=0`、解析失败均有对应提示。 ### 2. HTTP 明文或自签名证书报错? - Android 9+ 默认禁止明文 HTTP:请使用 **HTTPS**,或在宿主 **`network_security_config`** 中为更新域名放行明文(仅建议在可控环境)。 - 证书校验失败需在 OkHttp / 网络安全层单独处理(本库当前未暴露自定义 OkHttp)。 ### 3. Android 13+ 通知不显示? - 需 **`useInstallNotification = true`**,并动态申请 **`POST_NOTIFICATIONS`**(库内在点「立即更新」等时机请求;可先开 **`showNotificationPermissionRationale`** 做用途说明)。 - 用户拒绝时可走 Toast / 弹窗内按钮 / 直接安装等兜底。 - 系统「应用通知」总开关关闭时 likewise。 ### 4. 与 `Jetpack Compose` Activity? - 公开 API 入参为 **`AppCompatActivity`**,请使用 **`ComponentActivity`** 外包一层 **`AppCompatActivity`**,或对库做 fork/扩展接口。 --- ## 依赖传递说明 库内部使用 **Material、AppCompat(经 Material 传递)、OkHttp、Gson** 等。使用 **`implementation`** 发布的 AAR 在多数 Gradle 版本中会通过 **POM** 拉齐运行时依赖;若偶发 **`ClassNotFoundException`**,可在宿主 **显式** 加上与库 `build.gradle` 中一致的 **AndroidX / OkHttp / Gson** 版本。 --- ## License 若需要对外分发,请在仓库根目录补充与你项目一致的 **`LICENSE`** 文件。