Сбой при самообновлении APK (класс компонента не существует)
Я работаю над системным приложением, которое обновляет его, загружая 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 ...
Компонент "SomeOldReceiver" не существует в обновленном apk.
Кажется, что выполняется "старый" код из существующего APK (вызывается его приложение onCreate()), пытающееся получить доступ к "новому" манифесту, который существует в обновленном APK, и не может найти "старый" приемник (возможно ли это?).
Мое приложение также прослушивает PACAKGE_ADDED и PACKAGE_REMOVED намерения.
Этот сбой происходит на относительно большом проценте пользователей.
Любое предложение или подсказка о том, почему эта ошибка происходит и как ее исправить, будет очень признательна.
Ответы
Ответ 1
Существуют различные способы обновления APK. Я не уверен, какой из них вы используете. Я столкнулся с подобной проблемой.. и это было связано с тем, что приложение имеет несколько экземпляров во время обновления. Вы можете сделать приложение одним экземпляром или просто убедитесь, что не запущены старые экземпляры. Надеюсь, это поможет.
Ответ 2
Начиная с версии JELLY_BEAN:
Вызовы PackageManager.setComponentEnabledSetting
теперь будут вызывать IllegalArgumentException
, если данное имя класса компонента не существует в манифесте приложения.
Это объясняет, почему этот сбой происходит у большого процента пользователей.
Ответ 3
Извините, я не могу подтвердить, будет ли это какой-либо помощи, так как я сам ее не тестировал.
Возможно, вы можете попробовать отключить свой "SomeOldReceiver" (или любые другие компоненты, которые могут быть вызваны установкой нового пакета), сделав вызов setComponentEnabledSetting()
перед вызовом installPackage()
?
Логически, это может потребовать от вас создать промежуточную версию вашего приложения (которая добавила вызов setComponentEnabledSetting()
до installPackage()
и все еще должна иметь "SomeOldReceiver" в своем манифесте), чтобы сначала обновить старую версию. Затем вы можете обновить эту версию до вашей реальной обновленной версии с удаленным "SomeOldReceiver" .