Shrinking Xamarin.Android APKs with the Linker: A Practical Guide
Learn how to safely shrink Xamarin.Android APKs using the Linker, with configuration steps, a worked example, and verification tips.
19 Aug 2025, 23:51 UTC

Why APK size matters
Large Xamarin.Android APKs can deter users, especially on devices with limited storage or slow connections. Reducing the download size often improves install rates and retention, making it a worthwhile engineering goal.
Thesis
Enabling the Xamarin.Android Linker with a thoughtful configuration can cut the APK size significantly while keeping the app’s core functionality intact.
How the Linker works
The Linker performs static analysis on the intermediate language (IL) of your managed assemblies. It starts from a set of root types (e.g., Android activity classes, Xamarin.Forms entry points) and marks everything that is reachable. Anything not marked is considered unused and is stripped from the final package. This process removes whole types, methods, and even entire assemblies that the linker deems unnecessary.
Practical configuration steps
- Set the Linker behavior – In your Android project’s properties (or directly in the
.csprojfile), choose one of the following values for theAndroidLinkerproperty:SdkAssembliesOnly– links only Xamarin.Android and .NET libraries, leaving your own code untouched.LinkAll– attempts to link user assemblies as well (requires more preservation hints).
- Preserve reflection‑heavy code – If you use JSON.NET, custom renderers, or other reflection‑based frameworks, create a link description file (e.g.,
linker.xml) and reference it via theAndroidLinkerDescriptionFileproperty. A minimal example that preserves Xamarin.Essentials and Newtonsoft.Json looks like this:<linker> <assembly fullname="Xamarin.Essentials" preserve="all" /> <assembly fullname="Newtonsoft.Json" preserve="all" /> </linker> - Enable linking for Release builds only – Keep Debug builds unlinked for faster iteration. In the
.csprojyou can conditionally set the property:<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <AndroidLinker>SdkAssembliesOnly</AndroidLinker> <AndroidLinkerDescriptionFile>linker.xml</AndroidLinkerDescriptionFile> </PropertyGroup>
Worked example
Consider a simple Xamarin.Android app that uses Xamarin.Essentials for battery info and Newtonsoft.Json for settings persistence. After a clean Release build with the default settings (no linking), the APK size is approximately 28 MB. After applying the steps above — setting AndroidLinker to SdkAssembliesOnly and adding the linker.xml file — the same build yields an APK around 12 MB. The reduction comes from stripping unused Xamarin.Android support libraries and .NET runtime pieces that the app does not reference.
Note: The numbers above are illustrative; actual savings depend on the libraries you use and the amount of reflection‑based code in your project.
Trade‑offs and limitations
- Reflection risks – Types accessed only via reflection (e.g.,
Activator.CreateInstancewith a string name) can be removed, leading toMissingMethodExceptionorInvalidCastExceptionat runtime. Mitigate this by listing the affected assemblies or specific types in the linker description file. - Build time – Enabling the Linker adds static analysis steps, which can increase Release build duration by a few seconds to a minute, depending on project size.
- Debugging symbols – Linked builds may strip some debugging information, making it harder to trace issues that only appear after linking. Test thoroughly on a device or emulator before publishing.
Verification checklist
- Build the app in Release mode with the Linker enabled.
- Check the APK size using Android Studio’s APK Analyzer or run
aapt dump badging <path-to-apk>and compare the size to a baseline build without linking. - Run the app on a physical device or emulator and exercise the reflection‑heavy pathways (e.g., load a JSON settings file, invoke a custom renderer). Ensure no unexpected exceptions appear.
- If you encounter a MissingMethodException, add the missing type or assembly to
linker.xmland rebuild.
Actionable closing
Start small: enable SdkAssembliesOnly linking, verify that your app still runs, then consider moving to LinkAll if you need further size reductions and can invest time in tuning the linker description file. Regularly re‑run the verification checklist as you add new libraries, because each new dependency may introduce fresh reflection‑based entry points that need preservation.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.