Optimize your Xamarin.Android Builds

Jonathan Peppers

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.

Debug Builds

In Debug mode, your project has a single, simple goal: build fast. For your day-to-day development, the bulk of your time should not be spent waiting for builds. We want you writing code! Therefore, the APK size should not be a concern and startup time can be marginally slower.
 
The following settings are “must-haves” for Debug configurations.


1. Fast Deployment

Optimize your Xamarin.Android Builds Image 1

Without Fast Deployment, Xamarin.Android has to build an APK every time there’s change in your project, regardless of size or scope. This feature allows “side-loading” of .NET assemblies to enable a much better experience.

 

2. Multi-Dex

Optimize your Xamarin.Android Builds Image 2

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:

Optimize your Xamarin.Android Builds Image 4

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

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.

Optimize your Xamarin.Android Builds Image 7

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:

Optimize your Xamarin.Android Builds Image 8

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 .csproj file.

<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.

Other tricks

There are also a few general MSBuild settings that are helpful for improving Xamarin.Android build times.

1. DebugType

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 (full or 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.

Conclusion

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.

7 comments

Discussion is closed. Login to edit/delete existing comments.

  • Nino Padrutt 0

    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.

    • Jon DouglasMicrosoft employee 0

      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!

  • Mark Adamson 0

    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.

      • Mark Adamson 0

        super 🙂 thanks for the link

  • André Ziegler 0

    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?

    • André Ziegler 0

      ok, you need at least VS2019 GA/16.0 for ProduceReferenceAssembly to work correctly. 

Feedback usabilla icon