Xamarin Android app crashes when it was compiled with r8 shrinking Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Xamarin Android app crashes when it was compiled with r8 shrinking without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I want to make my app smaller. At first, I was tackling this with using proguard, then I found R8 today. I couldn’t achieve shrinking my app with proguard. Neither with R8.

I am using R8 with Visual Studio Professional 2019. Compilation successes with some warnings, but my app crashes after I compile my app with R8 in release mode. Same as proguard. Warnings are mentioned below. It works fine when it was compiled in debug mode or release mode without shrinking.

This is the device log that I get when I run the app on a phone. It happens during the app showed its splash.

12-02 07:56:06.459: E/AndroidRuntime(13285): FATAL EXCEPTION: main
12-02 07:56:06.459: E/AndroidRuntime(13285): Process: com.myproject.myproject, PID: 13285
12-02 07:56:06.459: E/AndroidRuntime(13285): android.runtime.JavaProxyThrowable: System.TypeInitializationException: The type initializer for 'Registry' threw an exception. ---> System.TypeInitializationException: The type initializer for 'DryIoc.WrappersSupport' threw an exception. ---> System.TypeInitializationException: The type initializer for 'DryIoc.ReflectionTools' threw an exception. ---> DryIoc.ContainerException: Undefined Method '"GetDefault"' in Type DryIoc.ReflectionTools (including non-public=True)
12-02 07:56:06.459: E/AndroidRuntime(13285):   at DryIoc.Throw.ThrowIfNull[T] (T arg, System.Int32 error, System.Object arg0, System.Object arg1, System.Object arg2, System.Object arg3) [0x0002b] in <b786dc28ccda4f9cada791c5ec73aee8>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at DryIoc.ReflectionTools.SingleMethod (System.Type type, System.String name, System.Boolean includeNonPublic) [0x00008] in <b786dc28ccda4f9cada791c5ec73aee8>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at DryIoc.ReflectionTools..cctor () [0x00000] in <b786dc28ccda4f9cada791c5ec73aee8>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):    --- End of inner exception stack trace ---
12-02 07:56:06.459: E/AndroidRuntime(13285):   at DryIoc.WrappersSupport..cctor () [0x000e6] in <b786dc28ccda4f9cada791c5ec73aee8>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):    --- End of inner exception stack trace ---
12-02 07:56:06.459: E/AndroidRuntime(13285):    --- End of inner exception stack trace ---
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Prism.DryIoc.PrismApplication.CreateContainerExtension () [0x00006] in <54b3690e7a884e5392d6564fe1058f17>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Prism.PrismApplicationBase.Initialize () [0x00000] in <69c22ecea5f44afaad9314eb228e8fb3>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Prism.PrismApplicationBase.InitializeInternal () [0x00006] in <69c22ecea5f44afaad9314eb228e8fb3>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Prism.PrismApplicationBase..ctor (Prism.IPlatformInitializer platformInitializer, System.Boolean setFormsDependencyResolver) [0x00038] in <69c22ecea5f44afaad9314eb228e8fb3>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Prism.PrismApplicationBase..ctor (Prism.IPlatformInitializer platformInitializer) [0x00000] in <69c22ecea5f44afaad9314eb228e8fb3>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Prism.DryIoc.PrismApplication..ctor (Prism.IPlatformInitializer platformInitializer) [0x00000] in <54b3690e7a884e5392d6564fe1058f17>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at myproject.App..ctor (Prism.IPlatformInitializer initializer) [0x00000] in <530a18ff74e7452ca04e0d812ab2f3ef>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at myproject.Droid.MainActivity.OnCreate (Android.OS.Bundle bundle) [0x0008c] in <c1eac816320349f19a935c6995da137f>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <f1027f4df0db4d02bec2ca8d90067419>:0 
12-02 07:56:06.459: E/AndroidRuntime(13285):   at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.10(intptr,intptr,intptr)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at md5bd5429e46ce9bb42cba5f37d4b72f961.MainActivity.n_onCreate(Native Method)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at md5bd5429e46ce9bb42cba5f37d4b72f961.MainActivity.onCreate(Unknown Source:0)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.Activity.performCreate(Activity.java:6986)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1232)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2863)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.ActivityThread.-wrap11(Unknown Source:0)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.os.Handler.dispatchMessage(Handler.java:105)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.os.Looper.loop(Looper.java:180)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at android.app.ActivityThread.main(ActivityThread.java:6950)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at java.lang.reflect.Method.invoke(Native Method)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
12-02 07:56:06.459: E/AndroidRuntime(13285):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:835)
12-02 07:56:06.464: E/ActivityManager(1722): App crashed! Process: com.myproject.myproject
12-02 07:56:07.026: E/[B+]AppInfoService(4722): null
12-02 07:56:07.026: E/[B+]AppInfoService(4722): android.os.DeadObjectException
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at android.os.BinderProxy.transactNative(Native Method)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at android.os.BinderProxy.transact(Binder.java:756)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at com.htc.pitroad.appminer.services.b$a$a.a(SourceFile:122)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at com.htc.pitroad.appminer.services.AppInfoService.a(SourceFile:852)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at com.htc.pitroad.appminer.b.a.a(SourceFile:119)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at com.htc.pitroad.appminer.e.o.a(SourceFile:154)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at com.htc.pitroad.appminer.services.AppInfoService.a(SourceFile:1747)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at com.htc.pitroad.appminer.e.p$a$1.invoke(SourceFile:77)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at java.lang.reflect.Proxy.invoke(Proxy.java:913)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at $Proxy0.onResult(Unknown Source)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at android.os.RemoteCallback.sendResult(RemoteCallback.java:73)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at android.os.RemoteCallback$2.sendResult(RemoteCallback.java:50)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at android.os.IRemoteCallback$Stub.onTransact(IRemoteCallback.java:56)
12-02 07:56:07.026: E/[B+]AppInfoService(4722):     at android.os.Binder.execTransact(Binder.java:682)

At the third line, I can see “DryIoc.ContainerException: Undefined Method ‘”GetDefault”‘ in Type DryIoc.ReflectionTools (including non-public=True)”. I assume that R8 deleted GetDefault method in DryIoc because I can see GetDefault method at line 12,052 on DryIoc code. https://github.com/dadhi/DryIoc/blob/master/src/DryIoc/Container.cs

Then I wrote “keep” in proguard.cfg like below. But it seems it doesn’t work. Error is the same and the size of the app is also the same.

-keep class dryioc.** { *; }

I’m not sure that it is related or not but I got some warnings when I compile this app with R8. It says there’s no way to resolve the confict between two mscrolib versions. So far, I can’t find a way to fix these warnings as well.

1>  myproject.Android -> C:Userskokisourcereposmyprojectmyprojectmyprojectmyprojectmyproject.AndroidbinReleasemyproject.Android.dll
1>  "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" と "mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" の間の競合を解決する方法がありません。一時的に、"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" を選択します。
1>C:Program Files (x86)Microsoft Visual Studio2019ProfessionalMSBuildXamarinAndroidXamarin.Android.D8.targets(81,5): warning XA4306: R8 does not support `MultiDexMainDexList` files when android:minSdkVersion >= 21
1>R8 : warning : The rule `-keep public class * extends androidx.versionedparcelable.VersionedParcelable {
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MSFTSIG.SF' already exists.
1>R8 : warning : Resource 'META-INF/MSFTSIG.RSA' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MSFTSIG.SF' already exists.
1>R8 : warning : Resource 'META-INF/MSFTSIG.RSA' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.
1>R8 : warning : Resource 'META-INF/MANIFEST.MF' already exists.

This is the current proguard.cfg under Android project.

-keep class android.support.v7.widget.** { *; }
-keep class android.support.v7.widget.FitWindowsLinearLayout { *; }

-keep class com.google.common.** { *; }
-dontwarn com.google.common.**

-keep class io.grpc.** { *; }
-dontwarn io.grpc.**

-keep class io.opencensus.trace.** { *; }
-dontwarn io.opencensus.trace.**

-keep class DryIoc.** { *; }

-keep class DryIoc.** {
    native <methods>;
}

-keepclassmembers class ** {
   public static *** GetDefault(***);
}

The last three rules about DryIoc seems not working. It makes no change for the size of the archived result.

Thanks!

Answer

Finally, I solved the problem.

What I did is, change Linking option from Sdk and User Assemblies into Sdk Assemblies Only on Android project.

I assumed that Sdk and User Assemblies preserves more codes than Sdk Assemblies Only, but apparently not.

Thank you for your help anyway!

We are here to answer your question about Xamarin Android app crashes when it was compiled with r8 shrinking - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji