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:\Users\koki\source\repos\myproject\myproject\myproject\myproject\myproject.Android\bin\Release\myproject.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 Studio\2019\Professional\MSBuild\Xamarin\Android\Xamarin.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!