如何无需Google Play Store实现APP自动更新与静默安装?
嘿,这个场景我刚好帮企业客户落地过,完全适配你的Kiosk设备私有托管自动更新需求,分两部分解决你的核心痛点:版本检测触发更新,以及无用户干预的静默安装,一步步给你讲清楚:
一、版本检测:让APP知道有新版本可用
这里给你两种实用方案,按需选择:
1. 定时拉取版本配置文件(最通用)
思路很简单:在客户的私有网站上放一个轻量的版本配置文件(比如version.json),里面存好最新版本的关键信息,APP定期去拉取对比,发现新版本就触发下载。
- 配置文件示例:
{ "version_code": 2, "version_name": "1.1.0", "apk_url": "https://客户私有域名/app/release/latest.apk", "apk_sha256": "xxxxxx..." // 可选,用于校验APK完整性 } - APP端实现(Kotlin示例):
可以用WorkManager做周期性任务(比如每6小时检查一次),或者APP前台常驻时在后台Service里触发:// 拉取并对比版本 fun checkRemoteVersion() { val client = OkHttpClient() val request = Request.Builder().url("https://客户私有域名/version.json").build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // 网络异常,记录日志下次重试 } override fun onResponse(call: Call, response: Response) { response.body?.string()?.let { jsonStr -> val json = JSONObject(jsonStr) val remoteVersionCode = json.getInt("version_code") val localVersionCode = BuildConfig.VERSION_CODE if (remoteVersionCode > localVersionCode) { // 触发下载流程 startDownloadApk(json.getString("apk_url")) } } } }) } - 注意:Kiosk模式下APP通常是前台常驻,用WorkManager能确保APP被系统回收后仍能执行检测任务。
2. 推送触发更新(更及时)
如果客户有自己的企业推送服务,新版本上线时直接给所有设备发推送,APP收到推送后立刻启动下载,不用等定时检测,适合紧急版本发布。
二、无用户干预的自动安装(核心难点)
这部分要重点关注Android版本权限差异,以及Kiosk模式的特殊权限优势:
1. 先搞定必要权限
在AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- 可选,确保开机后能继续检测 --> <!-- Android 10+ 不需要WRITE_EXTERNAL_STORAGE,用应用外部私有目录即可 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
- 关键提醒:Kiosk设备通常会被设置为设备所有者(这是企业管控Kiosk的常规操作),我们可以用设备所有者权限自动授予
REQUEST_INSTALL_PACKAGES,不用用户手动开启:val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager val adminComponent = ComponentName(this, YourDeviceAdminReceiver::class.java) if (dpm.isAdminActive(adminComponent)) { // 自动授予安装权限 dpm.setPermissionGrantState( adminComponent, packageName, Manifest.permission.REQUEST_INSTALL_PACKAGES, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED ) }
2. 静默安装实现(无用户确认)
普通APP做不到无交互安装,但Kiosk作为设备所有者应用,可以调用PackageInstaller实现静默安装,这是核心解决方案:
private fun installApkSilently(apkFile: File) { val packageInstaller = packageManager.packageInstaller val sessionParams = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL) val sessionId = packageInstaller.createSession(sessionParams) val session = packageInstaller.openSession(sessionId) // 把下载好的APK写入安装会话 val inputStream = FileInputStream(apkFile) val outputStream = session.openWrite("update_apk", 0, -1) inputStream.copyTo(outputStream) session.fsync(outputStream) inputStream.close() outputStream.close() // 提交安装请求,用BroadcastReceiver接收结果 val intent = Intent(this, InstallResultReceiver::class.java) val pendingIntent = PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) session.commit(pendingIntent.intentSender) session.close() } // 接收安装结果的广播接收器 class InstallResultReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val status = intent?.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE) when (status) { PackageInstaller.STATUS_SUCCESS -> { // 安装成功,自动重启APP restartApp(context) } else -> { val errorMsg = intent?.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) // 记录失败日志,下次检测时重试 } } } private fun restartApp(context: Context?) { val intent = context?.packageManager?.getLaunchIntentForPackage(context.packageName) intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) context?.startActivity(intent) // 杀死当前进程 android.os.Process.killProcess(android.os.Process.myPid()) } }
三、完整流程梳理
- 首次安装后,APP启动时立刻检查服务器版本配置
- 发现新版本,后台下载APK到应用外部私有目录(比如
getExternalFilesDir("apk")) - 下载完成后校验APK哈希值(可选),然后调用静默安装
- 安装成功后自动重启APP,完成更新
- 后台周期性检查版本,确保不会错过后续更新
四、额外注意事项
- APK完整性校验:下载后对比服务器返回的SHA256值,避免下载损坏或被篡改的文件
- 断点续传:用OkHttp的断点续传功能,避免网络中断后重新下载整个APK
- 存储空间检查:下载前确认设备剩余空间足够,避免安装失败
- 日志记录:把版本检测、下载、安装的全流程日志上传到客户的后台,方便排查问题
内容的提问来源于stack exchange,提问作者Android teem




