返回

安卓OTA升级INSTALL_FAILED_SHARED_USER_INCOMPATIBLE解决

Android

解决安卓 OTA 升级 APK 安装失败:INSTALL_FAILED_SHARED_USER_INCOMPATIBLE

老版本的安卓 OTA 升级 APK 安装不上,提示 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,这事儿挺让人头疼。别慌,下面咱们来分析一下,再想办法解决它。

一、 问题原因分析

安装老版本 OTA 升级 APK 时出现的 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE 错误,主要原因通常是 APK 的 sharedUserId 设置与系统中已存在的应用冲突。

sharedUserId 是 Android 系统中一个特殊的机制,允许具有相同 sharedUserId 的多个 APK 共享相同的用户 ID 和权限。这原本是为了方便厂商在不同应用间共享数据和资源。 但当两个 APK 的签名不一致,却拥有相同的 sharedUserId 时,系统就会出于安全考虑阻止安装,报出 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE 错误。

你的情况很可能是:

  1. 老版本的 OTA 升级 APK (com.oplus.ota) 设置了一个特定的 sharedUserId (比如 android.uid.system)。
  2. 手机系统升级后,内置的系统升级应用(可能包名或sharedUserId 改变了)已经使用了这个 sharedUserId
  3. 因为老版本的 APK 签名和内置应用签名不一致,所以安装失败。

二、 解决方案

既然知道了问题原因,我们就可以对症下药。下面提供几个可行的解决方案,你可以根据实际情况选择尝试。

1. 修改老 APK 的 sharedUserId (推荐)

这是最直接也最推荐的解决方案。通过修改老 APK 的 AndroidManifest.xml 文件,移除或更改 sharedUserId,可以避免与系统内置应用的冲突。

原理:

移除或修改sharedUserId后,老 APK 将不再尝试与系统应用共享用户 ID 和权限,从而绕过安装限制。

操作步骤:

  1. 准备工具:

    • apktool:用于反编译和重新打包 APK。
    • 文本编辑器:用于修改 AndroidManifest.xml 文件。
    • jarsignerapksigner:用于重新签名 APK (位于 Android SDK 的 build-tools 目录下)。
  2. 反编译 APK:

    apktool d -f old_ota.apk -o old_ota_decoded
    

    这条命令会将 old_ota.apk 反编译到 old_ota_decoded 文件夹。

  3. 修改 AndroidManifest.xml

    打开 old_ota_decoded/AndroidManifest.xml 文件,找到 android:sharedUserId 属性。
    有两种选择:

    • 直接删除 :直接删除包含android:sharedUserId的那一行。简单粗暴。
    • 修改 sharedUserId 将其值更改为一个独一无二的字符串, 例如: "com.yourname.ota". 这样更保险,避免将来和其他应用冲突。
  4. 重新打包 APK:

    apktool b old_ota_decoded -o old_ota_modified.apk
    

    这条命令会根据修改后的文件重新打包 APK。

  5. 重新签名 APK:
    这一步非常重要! 因为修改了 APK 内容, 必须重新签名才能安装。

    • 使用 jarsigner (老方法,但可能仍需 zipalign):

      jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 -keystore your-keystore.keystore -storepass your_keystore_password old_ota_modified.apk your_alias
      

      你需要将 your-keystore.keystore, your_keystore_password, 和 your_alias 替换为你自己的密钥库信息。如果没有自己的密钥库,需要先创建一个。

      如果使用 jarsigner,还需要运行zipalign:

      zipalign -v 4 old_ota_modified.apk old_ota_modified_aligned.apk
      

      zipalign的作用是对apk进行字节对齐, 提高运行效率.

    • 使用 apksigner (推荐,更简单):

    ```bash
    apksigner sign --ks your-keystore.keystore --ks-pass pass:your_keystore_password --out old_ota_signed.apk old_ota_modified.apk
    ```
    同样的,需要替换成你自己的密钥信息。
    
  6. 安装修改后的 APK:

    adb install old_ota_signed.apk  (或者 old_ota_modified_aligned.apk)
    

安全建议:

  • 创建密钥库和签名 APK 时,务必妥善保管密钥库文件和密码,防止泄露。
  • 确保你使用的工具 (apktool, jarsigner, apksigner) 来自可信来源。
  • 如果不清楚某些命令行工具的位置, 可以使用 find或者whereis 等命令去寻找他们。

进阶技巧:
可以使用 Apktool 的 --use-aapt2参数,它会在重新打包的时候使用 AAPT2 工具,有时候可以解决一些因为 AAPT 版本带来的兼容问题。 例如: apktool b --use-aapt2 old_ota_decoded -o old_ota_modified.apk

2. 尝试卸载系统内置的更新应用 (需要 Root)

如果你的手机已经 Root,可以尝试卸载系统内置的更新应用,然后再安装老版本的 APK。

原理:

卸载系统内置应用后,sharedUserId 冲突自然解除。

操作步骤:

  1. 获取 Root 权限: (此处不详细展开,请自行查阅你的机型Root 方式).

  2. 找到内置更新应用的包名:
    可以用以下方法确定:

    • 在设置 -> 应用管理 里面找到“系统更新”之类的应用,查看它的详细信息,一般可以看到包名。
    • 使用 adb shell pm list packages | grep ota (或 grep update) 等命令列出包含 "ota" 或 "update" 关键词的包名。
  3. 卸载应用:

    adb shell pm uninstall --user 0 <内置更新应用的包名>
    

    --user 0 参数表示卸载当前用户 (通常是用户 0) 的应用,而不是彻底删除。

安全建议:

  • Root 手机有风险,可能导致数据丢失或设备变砖,请谨慎操作。
  • 卸载系统应用前,务必确认包名,避免误删其他重要应用。
  • 某些厂商的系统可能会对系统应用做特殊保护,卸载后可能导致系统不稳定。

3. 使用 adb 禁用内置的更新应用(无需 Root)

这个方法尝试停用系统内置更新应用,虽然不能完全移除冲突,但或许可以规避部分问题。

原理:
禁用应用虽然不能从根本上移除SharedUserID冲突,但可以使其“隐身”,减少触发冲突的可能性。

操作步骤:

  1. 找到内置更新应用的包名: (同上,可以使用adb shell pm list packages 等命令。)
  2. 禁用应用:
adb shell pm disable-user --user 0 <内置更新应用的包名>

安全建议

  • 禁用系统应用可能会导致某些功能异常。如果操作之后遇到问题,可以重新启用。
  • 启用命令: adb shell pm enable <内置更新应用的包名>

4.使用虚拟机或者模拟器进行测试

如果你只是想简单测试一下这个老的OTA APK,又不想直接在真机上折腾, 可以考虑使用模拟器.

原理 :
新的模拟器环境通常不会内置和这个老APK冲突的sharedUserId

操作步骤 :

  1. 使用Android Studio 创建一个合适版本的模拟器 (比如 Android 12 的).
  2. 将老版本的 OTA APK 安装到模拟器中(adb install).
  3. 进行测试.

此方法比较简单,就不详细展开.

上面几种方法,建议先尝试第一种,因为它比较直接,风险也相对较小。 如果改了还是不行, 再尝试其他方案. 另外,具体命令中的占位符要记得替换成实际内容哦。