v10.53.1
English
Hardening follow-up to 10.53.0's PackageInstaller migration. No behaviour change on the healthy path, and no API change.
The APK install path can no longer throw into the bridge
A native module method runs on the native modules thread: a reject there is an ordinary error return, but a throw reaches React Native's exception handler and takes the app down. The 10.53.0 migration left three spots on downloadAndInstallApk able to throw instead of reject:
declaresInstallPermission()caught onlyNameNotFoundException, so any otherPackageManagerfailure escaped;install()acquired thePackageInstallerand built itsSessionParamsoutside thetry;downloadAndInstallApk()read its options (NoSuchKeyExceptionon the new architecture) and enqueued the download unguarded.
Every failure of this path now comes back as an APK_INSTALL_PERMISSION_REQUIRED or APK_INSTALL_FAILED rejection.
To be explicit about the question this came from: a missing REQUEST_INSTALL_PACKAGES declaration never crashed — 10.53.0 already rejected before starting the download, and it deliberately checks the manifest before calling canRequestPackageInstalls(), which itself throws SecurityException when the permission is not declared. Reporting is unchanged here: an incomplete integration still fails loudly and early, with no fallback path.
One contradictory outcome removed
If a session was committed successfully and only session.close() then failed, install() rejected the promise even though the system had already taken the install — while the status receiver was about to report the real outcome. The catch now settles nothing once the session is committed; from that point the receiver owns the result.
Verified by a standalone compile of the Android sources; the change is defensive only.
中文
针对 10.53.0 PackageInstaller 迁移的加固版本。正常路径行为不变,无 API 变更。
APK 安装路径不再可能把异常抛进 bridge
原生模块方法跑在 native modules 线程上:在那里 reject 是正常的错误返回,而 throw 会进入 React Native 的异常处理器、直接带崩应用。10.53.0 的迁移在 downloadAndInstallApk 上留了三处可能 throw 而非 reject 的地方:
declaresInstallPermission()只接了NameNotFoundException,PackageManager的其他失败会逃逸;install()获取PackageInstaller与构造SessionParams的几行在try之外;downloadAndInstallApk()读取参数(新架构下可能抛NoSuchKeyException)和入队下载没有保护。
现在这条路径的任何失败都会以 APK_INSTALL_PERMISSION_REQUIRED 或 APK_INSTALL_FAILED 的 promise 拒绝返回。
针对本次的起因明确一句:未声明 REQUEST_INSTALL_PACKAGES 从来不会崩溃——10.53.0 本就在开始下载前直接 reject,并且刻意先检查清单再调用 canRequestPackageInstalls()(该方法在权限未声明时自身会抛 SecurityException)。报错行为也没有变化:接入不完整依旧是提前、明确地报错,不做任何降级兜底。
移除一处矛盾结论
若会话已 commit 成功、仅 session.close() 报错,install() 之前仍会 reject——而此时系统已经接手安装,状态接收器正准备报告真实结果。现在 commit 之后 catch 不再 settle promise,结果一律由接收器给出。
已通过 Android 源码的独立编译验证;本次改动纯属防御性加固。