14

I am working on a system application which updates itslef by downloading an apk and installing it by using PackageManager's installPackage() method.

I am getting the following exception:

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 ...

The "SomeOldReceiver" component does not exist in the updated apk.

It seems like the "old" code from the existing APK is executed (its application's onCreate() is invoked) trying to access the "new" manifest that exists in the updated APK and can't find the "old" receiver (is this even possible?).

My app also listens to PACAKGE_ADDED & PACKAGE_REMOVED intents.

This crash happens on a relatively large percentage of users.

Any suggestion or clue as to why this bug is happening and how to fix it would be greatly appreciated.

lloydpick
  • 1,638
  • 1
  • 18
  • 24
Yuxal
  • 445
  • 4
  • 14
  • When do you get the exception? when does the code `com.myapp.package.utils.AndroidUtils.enableDisableComponent` run? – Blundell Mar 06 '16 at 14:42
  • `This crash happens on a relatively large percentage of users.` kind of makes me suspect it's due to the API incompatibility that occurred as the installPackage signature modified and/or the whole PackageManager region between platforms. It might be worth it to drop the PackageManager idea and return to the intent way? – L33T Mar 06 '16 at 14:44
  • Do you able to see starting which Android version this crash happens? – Geralt_Encore Mar 09 '16 at 14:02
  • @Geralt_Encore: yes. it's always from android 5.0.2 – Tal Kanel Mar 09 '16 at 14:03
  • 1
    Maybe cached (compiled) code is not invalidated automatically? Since application is running when package updating, native image is locked and isn't removed. When package installed, system tries to launch it to process broadcast, launches old native image and, obviously, catches an exception. – weaknespase Mar 09 '16 at 19:57
  • Do you have services running with START_STICKY or broadcast receivers either registered or listed in the (old) manifest that might be triggered by the update? – David Wasser Mar 11 '16 at 11:11

3 Answers3

0

There are different ways how to update APK..Im not sure which one you are using.. I faced similar issue .. and it was due to app has multiple instances during updating.. you can make app as single instance or just be sure there are not old instances running. I hope that may help.

Maher Abuthraa
  • 17,493
  • 11
  • 81
  • 103
  • how can I make an app to run as a single instance? – Tal Kanel Mar 09 '16 at 13:55
  • in manifest set android:launchMode="singleInstance" to your main activity – Maher Abuthraa Mar 09 '16 at 14:39
  • I don't think that setting launch mode for an activity affects application multiple instances vs single instance, it's affects only activity. either way - for the manner of speak: my application starts and updates itself without any activity ever been launcher at all – Tal Kanel Mar 09 '16 at 16:50
0

Since JELLY_BEAN version: Calls to PackageManager.setComponentEnabledSetting will now throw an IllegalArgumentException if the given component class name does not exist in the application's manifest.

It explains why this crash happens on a large percentage of users.

Geralt_Encore
  • 3,721
  • 2
  • 31
  • 46
0

Sorry, I cannot confirm whether this would be of any help since I haven't tested it myself.

Maybe you can try disabling your "SomeOldReceiver" (or any other components that might be triggered by the installation of the new package) by making a call to setComponentEnabledSetting() before calling installPackage() ?

Logistically, this might require you to produce an interim version of your app (that added the setComponentEnabledSetting() call before installPackage() and should still have "SomeOldReceiver" in its manifest) to update the old version first. You can then update this version to your real updated version with "SomeOldReceiver" removed.

Community
  • 1
  • 1
Joe
  • 14,039
  • 2
  • 39
  • 49