【问题标题】:Crash while self updating APK (component class does not exist)自更新 APK 时崩溃(组件类不存在)
【发布时间】:2016-03-30 17:35:38
【问题描述】:

我正在开发一个系统应用程序,它通过下载一个 apk 并使用 PackageManager 的 installPackage() 方法安装它来更新它。

我收到以下异常:

Fatal Exception: java.lang.IllegalArgumentException: Component class com.myapp.package.receivers.SomeOldReceiver does not exist in com.myapp.package
           at android.os.Parcel.readException(Parcel.java:1544)
           at android.os.Parcel.readException(Parcel.java:1493)
           at android.content.pm.IPackageManager$Stub$Proxy.setComponentEnabledSetting(IPackageManager.java:3420)
           at android.app.ApplicationPackageManager.setComponentEnabledSetting(ApplicationPackageManager.java:1492)
           at com.myapp.package.utils.AndroidUtils.enableDisableComponent(SourceFile:113)
           at ...

更新后的 apk 中不存在“SomeOldReceiver”组件。

似乎执行了现有 APK 中的“旧”代码(调用了其应用程序的 onCreate()),试图访问更新后的 APK 中存在的“新”清单,但找不到“旧”接收器(这甚至可能吗?)。

我的应用还监听 PACAKGE_ADDED 和 PACKAGE_REMOVED 意图。

这种崩溃发生在相对较大比例的用户身上。

任何关于为什么会发生此错误以及如何修复它的建议或线索将不胜感激。

【问题讨论】:

  • 什么时候得到异常?代码com.myapp.package.utils.AndroidUtils.enableDisableComponent什么时候运行?
  • This crash happens on a relatively large percentage of users. 有点让我怀疑这是由于在 installPackage 签名修改和/或平台之间的整个 PackageManager 区域时发生的 API 不兼容。放弃 PackageManager 的想法并返回意图方式可能值得吗?
  • 你能看到这个崩溃发生在哪个 Android 版本上吗?
  • @Geralt_Encore:是的。它总是来自 android 5.0.2
  • 也许缓存(编译)的代码不会自动失效?由于包更新时应用程序正在运行,因此本机映像被锁定并且不会被删除。安装包后,系统会尝试启动它来处理广播,启动旧的原生镜像,显然会捕获异常。

标签: android android-manifest android-install-apk android-broadcastreceiver


【解决方案1】:

更新 APK 有不同的方法..我不确定您使用的是哪一个..我遇到了类似的问题..这是由于更新期间应用程序有多个实例..您可以将应用程序作为单个实例或只要确保没有旧实例在运行。我希望这可能会有所帮助。

【讨论】:

  • 如何让应用程序作为单个实例运行?
  • 在清单中将 android:launchMode="singleInstance" 设置为您的主要活动
  • 我不认为为活动设置启动模式会影响应用程序的多个实例与单个实例,它只影响活动。无论哪种方式-就说话方式而言:我的应用程序启动并自行更新,而根本没有任何活动是启动器
【解决方案2】:

Since JELLY_BEAN version: 如果给定的组件类名称在应用程序的清单中不存在,则对 PackageManager.setComponentEnabledSetting 的调用现在将抛出 IllegalArgumentException

它解释了为什么大部分用户会发生这种崩溃。

【讨论】:

    【解决方案3】:

    抱歉,我无法确认这是否有帮助,因为我自己没有测试过。

    也许您可以通过在调用installPackage() 之前调用setComponentEnabledSetting() 来尝试禁用“SomeOldReceiver”(或任何其他可能由安装新软件包触发的组件)?

    从逻辑上讲,这可能需要您生成应用程序的临时版本(在 installPackage() 之前添加了 setComponentEnabledSetting() 调用,并且清单中仍应包含“SomeOldReceiver”)以首先更新旧版本。然后,您可以将此版本更新为真正的更新版本,并删除“SomeOldReceiver”。

    【讨论】:

      猜你喜欢
      • 2019-04-12
      • 2020-03-26
      • 1970-01-01
      • 1970-01-01
      • 2017-02-16
      • 1970-01-01
      • 2023-02-08
      • 2017-05-28
      • 1970-01-01
      相关资源
      最近更新 更多