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

Android 12(API31)下Package Installer失效问题排查咨询

Android 12联想M9(TB310XU)设备应用版本更新代码失效问题排查

问题背景

原代码可在Android 10及更早版本、联想M8 4代(TB300XU)设备上正常实现应用版本更新,但在Android 12(API 31)的联想M9(TB310XU)设备上失效,抛出空指针异常:

Failed query: java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.database.Cursor.moveToFirst()' on a null object reference

完整堆栈关键调用链:

android.os.Parcel.createExceptionOrNull(Parcel.java:2425)
android.os.Parcel.createException(Parcel.java:2409)
android.os.Parcel.readException(Parcel.java:2392)
android.os.Parcel.readException(Parcel.java:2334)
android.content.pm.IPackageInstallerSession$Stub$Proxy.fsync(IPackageInstallerSession.java:730)
android.content.pm.PackageInstaller$Session.fsync(PackageInstaller.java:967)
// 最终指向代码中的session.fsync(outputStream)调用

原实现代码

val inputStream =
    context.applicationContext.contentResolver.openInputStream(Uri.fromFile(file))
val length =
    DocumentFile.fromSingleUri(context.applicationContext, Uri.fromFile(file))!!
        .length()
val installer = context.applicationContext.packageManager.packageInstaller
val params = SessionParams(SessionParams.MODE_FULL_INSTALL)
val sessionId = installer.createSession(params)
val session = installer.openSession(sessionId)
val outputStream = session.openWrite(file.name, 0, length)
val buf = ByteArray(1024)
var len: Int
while (inputStream!!.read(buf).also { len = it } > 0) {
    outputStream.write(buf, 0, len)
}
session.fsync(outputStream)
outputStream.close()
inputStream.close()

val intent = Intent(context.applicationContext, DeviceReceivers::class.java)

val pi = PendingIntent.getBroadcast(
    context.applicationContext,
    REQUEST_INSTALL_PACKAGE,
    intent,
    PendingIntent.FLAG_UPDATE_CURRENT // FLAG_IMMUTABLE for android 12
)

session.commit(pi.intentSender)
session.close()

排查步骤

  • 定位触发点:从堆栈看异常出现在session.fsync(outputStream),系统底层查询Cursor返回null,优先怀疑文件URI权限或厂商定制实现差异。
  • 替换文件URI生成方式:放弃Uri.fromFile(file),改用FileProvider生成content://格式URI,确保系统安装服务能正常访问文件。需在AndroidManifest配置FileProvider,并通过getUriForFile生成URI。
  • 修正PendingIntent Flag:Android 12强制要求PendingIntent指定FLAG_IMMUTABLE或FLAG_MUTABLE,将代码中的Flag替换为PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE(若无需修改广播Intent则用IMMUTABLE)。
  • 简化文件长度获取:DocumentFile.fromSingleUri处理file://URI可能存在厂商bug,直接用file.length()获取文件大小,避免依赖系统DocumentFile实现。
  • 验证文件状态:在打开输入流前添加file.exists()和file.canRead()检查,确认安装包文件存在且当前应用有读取权限。
  • 检查安装会话参数:给SessionParams补充配置,比如params.setInstallLocation(SessionParams.INSTALL_LOCATION_AUTO),同时确认设备所有者应用已获取MANAGE_DEVICE_ADMINS及安装相关权限。
  • 抓取系统日志:通过adb logcat -s PackageInstaller过滤系统安装服务日志,查看是否有文件访问拒绝、会话创建失败等详细错误信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:57:44