You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用自更新后崩溃:Failed to measure fs-verity, errno 1问题排查

APK更新后崩溃:fs-verity测量失败问题排查

我正在为Android应用添加外部APK链接自更新功能。从外部链接下载新版APK后,通过PackageInstaller完成更新,能看到新版本UI的新增文本(说明更新成功),但启动应用时崩溃,报错如下:

VerityUtils pid-594 E  Failed to measure fs-verity, errno 1: /data/app/~~QTV2DULtWFYdJpO7yGn7sg==/com.test.app--JKzM4i9A3BAuvFAm9x9YQ==/base.apk

我怀疑APK文件损坏,但更新后能正常显示新UI的情况与此矛盾。另外,应用已拥有设备所有者权限,以下是实现代码:

class UpdateAppViewModel(application: Application): AndroidViewModel(application) {
    fun download() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                val fileUrl = "https://my-path-to-ne-apk-s3.net/test-app"

                val intent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
                    data = Uri.parse(fileUrl)
                    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK
                }
                Log.d("UPD", "START DOWNLOAD")

                val packageInstaller = getApplication<Application>().packageManager.packageInstaller
                val sessionParams = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
                val sessionId = packageInstaller.createSession(sessionParams)
                val session = packageInstaller.openSession(sessionId)

                val inputStream = URL(fileUrl).openStream()
                val outputStream = session.openWrite("test-app.apk", 0, -1)
                inputStream.copyTo(outputStream)
                session.fsync(outputStream)
                inputStream.close()
                outputStream.close()
                Log.d("UPD", "FINISH DOWNLOAD")

                val pendingIntent = PendingIntent.getBroadcast(getApplication<Application>().applicationContext, 0, intent, 0)
                Log.d("UPD", "BEFORE COMMIT!")
                session.commit(pendingIntent.intentSender)
                Log.d("UPD", "AFTER COMMIT!")
                session.close()
            }
        }
    }
}

请问该报错的原因是什么?


问题分析与原因

1. 报错本质

fs-verity是Android系统用于验证APK文件完整性的安全机制,会在应用启动时校验APK哈希值是否与安装时记录的一致。报错中的errno 1对应EPERM(权限不足),意味着系统读取APK进行完整性测量时权限不够,进而判定APK可能被篡改或损坏,最终触发崩溃。

2. 代码中的核心问题

  • 错误的PendingIntent配置:你用Intent.ACTION_INSTALL_PACKAGE创建的是触发系统安装器的动作intent,但PackageInstaller的commit方法需要的是接收安装结果的广播intent。错误的intent会破坏安装流程的权限上下文,导致后续fs-verity校验的权限环境异常。
  • 缺失APK完整性校验:虽然更新后能显示新UI,但APK可能因网络波动出现部分字节丢失——APK结构未损坏(能解析资源和代码),但完整性哈希值不匹配,触发fs-verity校验失败。
  • Session关闭时机错误:session.close()在commit后立即执行,而commit是异步操作,此时Session可能还未完成APK的最终写入和权限配置,提前关闭会导致APK文件的权限或完整性出现异常。

3. 关键修复方向

  • 替换为专用广播接收PendingIntent:创建自定义BroadcastReceiver处理安装结果,用该广播的intent生成PendingIntent传入session.commit。
  • 添加APK完整性校验:下载完成后计算APK的SHA-256哈希值,与服务器提供的校验值对比,确认文件完整后再执行安装。
  • 调整Session关闭时机:在BroadcastReceiver的回调(收到安装完成通知)中再调用session.close(),确保安装流程完全结束。

内容的提问来源于stack exchange,提问作者Rostislav Shtanko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:32:54