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

使用PackageInstaller安装APK时无法获取状态更新求助

问题分析与解决方案

核心问题1:PendingIntent不可变性阻止系统注入额外数据

你创建PendingIntent时使用了PendingIntent.FLAG_IMMUTABLE,在Android 12(API 31)及以上版本,该标记会让Intent变为不可修改状态,而PackageInstaller需要向Intent中写入安装状态、包名等数据,因此无法完成注入。

修复代码:根据系统版本替换为FLAG_MUTABLE(低版本可保留原标记):

val pi = PendingIntent.getBroadcast(
    context,
    InstallReceiver::class.hashCode(),
    intent,
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
    } else {
        PendingIntent.FLAG_UPDATE_CURRENT
    }
)

核心问题2:未在SessionParams中指定目标包名

你的SessionParams未设置要安装APK的包名,PackageInstaller无法识别目标应用,因此无法传递EXTRA_PACKAGE_NAME等关键数据。

修复代码:解析APK包名并绑定到SessionParams:

// 在创建params后添加这段代码
val packageInfo = context.packageManager.getPackageArchiveInfo(
    apk.absolutePath,
    PackageManager.GET_META_DATA
)
packageInfo?.packageName?.let { packageName ->
    params.setAppPackageName(packageName)
}

其他潜在修复点

  1. 广播接收器XML配置错误:原配置标签未正确闭合,修正后:
<receiver android:name=".shared.updater.InstallReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="xx.xx.installer.InstallReceiver.ACTION_INSTALL" />
    </intent-filter>
</receiver>
  1. Session资源优化:使用use块自动管理Session生命周期,避免手动关闭的潜在问题:
// 替换原session.openSession后的代码块
context.packageManager.packageInstaller.openSession(sessionId).use { session ->
    apk.inputStream().use { apkStream ->
        session.openWrite(apk.nameWithoutExtension, 0, apk.length()).use { sessionStream ->
            apkStream.copyTo(sessionStream)
            session.fsync(sessionStream)
        }
    }
    // 此处执行commit操作
    session.commit(pi.intentSender)
}

修改后的完整安装方法示例

override suspend fun installUpdates(): Unit = withContext(Dispatchers.IO) {
    try {
        apkDirectory.listFiles()?.forEach { apk ->
            val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
            
            // 解析APK包名并设置
            val packageInfo = context.packageManager.getPackageArchiveInfo(
                apk.absolutePath,
                PackageManager.GET_META_DATA
            )
            packageInfo?.packageName?.let {
                params.setAppPackageName(it)
            }

            val sessionId = context.packageManager.packageInstaller.createSession(params)
            context.packageManager.packageInstaller.openSession(sessionId).use { session ->
                apk.inputStream().use { apkStream ->
                    session.openWrite(apk.nameWithoutExtension, 0, apk.length()).use { sessionStream ->
                        apkStream.copyTo(sessionStream)
                        session.fsync(sessionStream)
                    }
                }

                val intent = Intent(context, InstallReceiver::class.java)
                intent.action = InstallReceiver.ACTION_INSTALL
                val piFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
                } else {
                    PendingIntent.FLAG_UPDATE_CURRENT
                }
                val pi = PendingIntent.getBroadcast(
                    context,
                    InstallReceiver::class.hashCode(),
                    intent,
                    piFlags
                )

                session.commit(pi.intentSender)
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

完成以上修改后,广播接收器即可接收到完整的安装状态、包名、会话ID等数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:56:07