Streetcomplete: BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR on class

Created on 8 Aug 2020  路  1Comment  路  Source: westnordost/StreetComplete

How to Reproduce
Start application

Versions affected
Streetcomplete v22, Mi 9T Pro, Android 9

Applicatio crashes when I press on icon, but with second attempt it is possible to start. Mi UI gave me such stacktrace, not sure is it helpful. I can attach app logs if you let me know where they are located. Thanks.

java.lang.RuntimeException: Unable to start activity ComponentInfo{de.westnordost.streetcomplete/de.westnordost.streetcomplete.MainActivity}: android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR on class androidx.fragment.app.FragmentManagerState
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2991)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3126)
 at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
 at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
 at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1846)
 at android.os.Handler.dispatchMessage(Handler.java:106)
 at android.os.Looper.loop(Looper.java:201)
 at android.app.ActivityThread.main(ActivityThread.java:6882)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Caused by: android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR on class androidx.fragment.app.FragmentManagerState
 at android.os.Parcel.readParcelableCreator(Parcel.java:2851)
 at android.os.Parcel.readParcelable(Parcel.java:2768)
 at android.os.Parcel.readValue(Parcel.java:2671)
 at android.os.Parcel.readArrayMapInternal(Parcel.java:3045)
 at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
 at android.os.BaseBundle.unparcel(BaseBundle.java:232)
 at android.os.BaseBundle.getBoolean(BaseBundle.java:903)
 at android.app.Activity.restoreHasCurrentPermissionRequest(Activity.java:7584)
 at android.app.Activity.performCreate(Activity.java:7226)
 at android.app.Activity.performCreate(Activity.java:7221)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2971)
 ... 11 more
bug

Most helpful comment

The problem is R8, Android's code shrinker and obfuscator which removes unused code. It identifies that CREATOR object as unused because it is only accessed via reflection and removes it.

The default configuration file for R8, proguard-android-optimize.txt which I also use actually tells R8 to not trash CREATOR:

-keepclassmembers class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator CREATOR;
}

...but apparently that doesn't work. I added ...

-keepclassmembers class * implements android.os.Parcelable {
        public static final ** CREATOR;
}

...to the local R8 configuration file.

When adding -printusage [filename] to the end of the configuration file, R8 will output all the things it removed into the given file. I did that for both the current situation and after I added the additional rule and then looked at the diff between the two files.
The additional rule made it so that things like ...

androidx.preference.PreferenceGroup$SavedState:
    public static final android.os.Parcelable$Creator CREATOR

...were not removed anymore.

So maybe this is a bug in R8 that it does not apply the rule in proguard-android-optimize.txt correctly, though if that was the case, StackOverflow or Google's bugtracker should be full of this. So I am not sure what is going on but my additional rule seems to fix it.

I am writing this here in such a detailed manner so that people who search for this problem in the future might find this explanation and workaround.

>All comments

The problem is R8, Android's code shrinker and obfuscator which removes unused code. It identifies that CREATOR object as unused because it is only accessed via reflection and removes it.

The default configuration file for R8, proguard-android-optimize.txt which I also use actually tells R8 to not trash CREATOR:

-keepclassmembers class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator CREATOR;
}

...but apparently that doesn't work. I added ...

-keepclassmembers class * implements android.os.Parcelable {
        public static final ** CREATOR;
}

...to the local R8 configuration file.

When adding -printusage [filename] to the end of the configuration file, R8 will output all the things it removed into the given file. I did that for both the current situation and after I added the additional rule and then looked at the diff between the two files.
The additional rule made it so that things like ...

androidx.preference.PreferenceGroup$SavedState:
    public static final android.os.Parcelable$Creator CREATOR

...were not removed anymore.

So maybe this is a bug in R8 that it does not apply the rule in proguard-android-optimize.txt correctly, though if that was the case, StackOverflow or Google's bugtracker should be full of this. So I am not sure what is going on but my additional rule seems to fix it.

I am writing this here in such a detailed manner so that people who search for this problem in the future might find this explanation and workaround.

Was this page helpful?
0 / 5 - 0 ratings