2

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!

Koki
  • 31
  • 6
  • Which version of ProGuard are you using – R15 Dec 02 '19 at 06:59
  • Thank you for the comment. I'm using version 6.2. I followed the link below to install the latest proguard. https://learn.microsoft.com/en-us/xamarin/android/deploy-test/release-prep/proguard?tabs=windows#proguard-and-android-nougat – Koki Dec 02 '19 at 07:31
  • Check this https://stackoverflow.com/questions/57601897/android-studio-3-5-warning-the-rule-keep-public-class-extends-androidx-vers and https://stackoverflow.com/questions/58164301/how-to-use-proguard-optimizer-tool-with-xamarin-forms – R15 Dec 02 '19 at 09:35
  • For the first link, I could find files which are written "-keep public class * extends androidx.versionedparcelable.VersionedParcelable" only in "C:\Users\koki\source\repos\myproject\myproject\myproject\myproject\myproject.Android\obj\Release\90\lp\53\jl". When I changed extends into implements, the warning was suppressed but the app keeps crashing. For the second link, I have my proguard.cfg. I'll put my proguard.cfg. – Koki Dec 02 '19 at 22:48
  • For the first link when crashing what is the exception in log? – R15 Dec 03 '19 at 06:07
  • The exception log is exactly the same as former one. Can't find GetDefault method. – Koki Dec 03 '19 at 07:17
  • in ProGuard file(which is in your android project level) write the rule `-keep public class * extends androidx.versionedparcelable.VersionedParcelable`. For proguard configuration follow link 2 – R15 Dec 03 '19 at 07:47
  • Thanks. I followed the steps and updated proguard. No luck so far, and the error is the same. As you recommended, I put the line in proguard.cfg, but made no difference. – Koki Dec 03 '19 at 22:17

1 Answers1

1

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!

Koki
  • 31
  • 6