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
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.
Most helpful comment
The problem is R8, Android's code shrinker and obfuscator which removes unused code. It identifies that
CREATORobject 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:...but apparently that doesn't work. I added ...
...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 ...
...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.