Introduction
In my Play Store Organic Traffic post I commented that I need to work on ASO (App Store Optimisation) for my app Seed:Loops . Since then my conversion rate has dropped further to a shade under 15%. The app file size is a potential reason for a low conversion rate as explained in the Google Play Console.
App size can affect your app’s install and uninstall metrics, so it’s important to monitor and optimise your app’s download and on-device sizes
My app bundle (.aab file) size before making any changes was 64.4MB.
Compressing Assets
The log hanging fruit was the sound font (.sf2 file). I use library called Bass which is a great audio library. I had already used its sf2pack tool to compress the sound font with a lossless algorithm but there was scope to more aggressively compress it with a lossy algorithm. Having tested both it doesn’t negatively impact the sound so I opted to keep the smaller file.
This reduced the sound font file size by a further 10MB.
Xamarin Linker
The Xamarin Linker Docs details how to enable linking and some of the pitfalls. By enabling it my app I fell directly into them. After deploying a release build and starting the app it immediately crashed.
Debugging Linker Errors
I found the easiest way to debug this was to run the following from a PowerShell terminal.
adb logcat | Select-String seedloops
By piping the output into Select-String and filtering to my app name it removes a lot of noise.
The word “Exception” caught my eye so used ctrl-c
to break out of it and executed
adb logcat | Select-String Exception
This told me what had been removed by the linker
09-22 23:01:56.275 3295 3295 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.ads.MobileAdsInitProvider" ...
A ClassNotFoundException for com.google.android.gms.ads.MobileAdsInitProvider.
The problem is that doesn’t translate to the assembly name that I added via nuget for Mobile Ads. To work this out I used one of my favourite tools ILSpy . ILSpy decompiles .net assemblies so it can be used to inspect classes within a dll. By dragging/dropping all the dlls from the obj\Release\120\androidx\cecil folder into it I could search for MobileAdsInitProvider to work out Xamarin.GooglePlayServices.Ads.Lite assembly contained it.
(Assemblies list trimmed in the above screenshot as it was right at the bottom!)
This needed adding to Skip Linking Assemblies section in the project properties of the Android project.
I had to iterate on this process, working through another ClassNotFoundException….
09-22 23:36:17.480 9563 9563 E AndroidRuntime: java.lang.RuntimeException: Unable to get provider androidx.startup.InitializationProvider: java.lang.ClassNotFoundException: ...
And ultimately my own class constructors being linked out with the System.MissingMethodException: Default constructor not found
error referenced in the docs. This was due to my use of the service
locator pattern meaning there are no direct references to them in code.
The final string in my skip linking assemblies section was.
Xamarin.GooglePlayServices.Ads.Lite;Xamarin.AndroidX.Startup.StartupRuntime;SeedLoops
ProGuard
Skipping asseblies did not fix all of my errors. There was one ClassNotFoundException which wasn’t (obviously) found by searching the dependencies.
09-23 00:08:20.568 13773 13773 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: androidx.appcompat.widget.FitWindowsLinearLayout
To overcome this I used a ProGuardConfiguration.cfg file as detailed in the Xamarin Docs. I added the file to my Android project, set the build action in the properties tool box to ProguardConfiguration, and added the following line to it.
-keep public class androidx.appcompat.widget.FitWindowsLinearLayout { *; }
This works with the default code shrinker r8 selected (I did not have to change it to ProGuard).
Now the app starts and all features works as excepted.
Final Bundle Size
The aab file is now 40.75MB which is over a one third reduction in the compiled artefact.
The App Size section in the Google Play Console shows the download size broken down by assets, code etc. The charts for before and after show it’s nearer 50% in terms of actual download size!
Conclusion
I’m yet to see whether this has had a measurable impact on conversions but I’m hopeful it will. I still have more ASO to do. Next on the list is a concise video detailing its features.