Optimize your Xamarin.Android Builds
Xamarin.Android has a lot of nobs and levers when it comes to configuring your project. For example, do you know what the best settings are in Debug mode for quick builds? Or what to do in Release mode to make your APK as small as possible or have the fastest startup time? In this post, we will look into how you can optimize your Xamarin.Android builds to give you the best results for your mobile apps.
The following settings are found in the Xamarin.Android project
Properties... screen in Visual Studio on Windows and in the
Options screen in VS for Mac. At the time of writing, I was using Visual Studio 2019 16.2 and VS for Mac 8.2.
1. Fast Deployment
Enable Multi-Dex should be unchecked: unless your app fails to build without it. Xamarin.Android applications under the dex limit should not need this setting. See my recent blog post on how fewer projects will need Multi-Dex when using Visual Studio 2019 16.2 or higher.
3. Release-only Settings
The following settings should likewise be disabled for Debug builds:
Using AOT, Linking, or a Code Shrinker for Debug configurations is not that helpful. They will slow down your Debug builds with no real benefit.
Release builds have two goals that are sometimes at odds with each other:
- Smallest APK size
- Fastest startup time
1. Linking and Shrinking
Linking all of your application’s .NET assemblies is the first step to get a smaller APK. Managed DLLs have to be left uncompressed in your APK, so assemblies will directly contribute to the overall file size.
Many Xamarin.Android applications can just toggle this setting; however, if you take advantage of
System.Reflection it is possible the linker can remove types your application uses. Check out our documentation on linking for details.
Likewise, your application should enable a Java Code Shrinker, such as ProGuard. This shrinks compiled Java code in your application, which can also strip too much code in some cases. ProGuard rules allow developers to be specific about which Java classes must be kept.
2. Ahead of Time (AOT)
Mono’s AOT compiler will transform your .NET assemblies into native code “ahead of time”. This produces Android applications with a faster startup and better overall performance, at the cost of a larger APK.
However, a new feature in Visual Studio 2019 16.2,
Enable Startup Tracing, allows you to enable AOT for only the startup path of your application. It is a “best of both worlds” trade off that only slightly increases APK sizes. Read more on the subject in Faster Startup Times with Startup Tracing on Android.
New Xamarin.Android Features
1. Android Asset Packaging Tool (aapt)
AAPT is responsible for processing Android resource files and creating the “base” of an APK. aapt2 is a new implementation that vastly improves performance for incremental builds. If you author your UIs with Android XML layouts, then this setting is a must:
aapt2 will soon be the default in future Xamarin.Android releases, so give it a try today.
2. d8 and r8
d8 and r8, are an easy improvement to enable in your app if you have not already. Keep in mind that the r8 Code Shrinker (just like ProGuard) is meant to be enabled for Release builds.
Using d8 by itself will improve build times and make your APK a bit smaller. r8 is the companion to d8, giving you the same features as ProGuard.
3. Android App Bundles
App Bundles are a new publishing format for Android applications. When using App Bundles, Google Play will create a custom set of APK files for each user’s device, so they only download what is needed. App Bundles are split up based on CPU, language, screen density, etc.
In Visual Studio 2019 16.2, we have initial preview support for producing App Bundles for your application. You can enable the feature for your Release build, by modifying your
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <AndroidPackageFormat>aab</AndroidPackageFormat> </PropertyGroup>
In future releases, we will have new publishing workflows to make App Bundle submission even easier. For details about trying App Bundles today, see our release notes for Xamarin.Android 9.4.
There are also a few general MSBuild settings that are helpful for improving Xamarin.Android build times.
A little known setting in all
.csproj files is the “Debug Type” of a .NET project:
portable– the cross-platform format that Mono and Xamarin supports.
full– a Windows-specific format for Debug builds
pdbonly– a Windows-specific format for Release builds
If your project is not using
portable, then Xamarin.Android has to convert the symbols. This setting is specifically important for NuGet authors targeting Xamarin. Using the wrong one (
pdbonly) will require all consumers of your package to spend that extra build time.
2. Reference Assemblies in NetStandard Projects
Reference assemblies are a new feature of Roslyn and MSBuild. By default, if C# code in an assembly changes, then any other project referencing it must also rebuild. Reference assemblies help this situation because the other projects will not build unless the public API changes.
You can enable this by manually by editing the csproj files of a .NET Standard library:
<PropertyGroup> <ProduceReferenceAssembly>True</ProduceReferenceAssembly> </PropertyGroup>
This setting allows you to modify XAML in a Xamarin.Forms .NET Standard project, and the C# compiler can be skipped for the Xamarin.Android application project.
Xamarin.Android project settings can be somewhat complicated because they provide .NET developers full access to the Android platform. We have plans to simplify things in future releases and make it easier to work with project settings, so make sure to stay tuned.
For an even deeper dive, check out my talk from Xamarin Developer Summit 2019 in Houston, Texas.
Thanks for the post! What I’m still kinda puzzled is about the AOT modes, I saw a couple of posts describing how I can activate them. But as far as I know these a exclusive features of Visu Studio Enterprise. Or did that change? (Last time I tried to add the flags manually they where ignored). If that still is the case that might be worth a note. Could save quite some time for all on the community edition.
There are two AOT modes today. Traditional AOT, which is still an enterprise feature, and Startup Tracing(Profiled AOT), which can be used on any edition of Visual Studio on 16.2+ / Visual Studio for Mac 8.2+. https://devblogs.microsoft.com/xamarin/faster-startup-times-with-startup-tracing-on-android/
We are still working to flush out this experience with UI options and even potentially enabling it by default so you don’t have to worry about it. However stay tuned for future blog posts about this!
If you have any difficulty enabling Startup Tracing, please report an issue within your IDE!
Addressing the last point about complexity, it would be great if you added support for SDK project format and use that to set all of these sensible defaults in the SDK so that our project files would just be very simple for the ideal settings and most small app developers wouldn’t need to worry about checking the settings as new improvements come along.
This is something we are working on! https://github.com/xamarin/xamarin-android/projects/13
Thank you for the feedback as our goal is to make project files as simple as possible in the future.
super 🙂 thanks for the link
I’ve set the ProduceReferenceAssembly to true in csproj of my .net standard 2.0 project, but Android app has to be build again, because VS writes in build output that the android app is not up to date as bin\Debug\ref\FooApp.dll is modified after output file if I modify only a XAML file.
I use VS2017 15.9.14. Does this require VS2019?
ok, you need at least VS2019 GA/16.0 for ProduceReferenceAssembly to work correctly.