Your Xamarin app can be deployed to a large array of mobile devices, each with a different CPU architecture, and SDK version. You define which SDK and CPU architecture you want to support, in your project’s properties and the build tasks will ensure the right binaries are then created. The settings you choose, will result in what device’s and OS’s your app can run on.
First, lets look at CPU architectures. This is based upon the type of CPU that is running in the device.
Important Note: For each CPU Architecture you choose, it will increase the size of your application package, as it must compile for each architecture you want to support. Hence, there is a balancing act between support, performance and file size.
Physical iOS devices, such as iPhones and iPads will use ARM based CPUs. When you are developing on your Mac, the simulator is running on an i386 or x86 based processor.
If you are developing on your simulator, you will want to use x86_64. Please note that while you can run using i386 + x86_64, UITest no longer supports this configuration.
Deciding what to choose for this option, depends upon what devices you want to support. Here are some comparisons for iPhones.
ARMv6 – iPhone & iPhone 3G
ARMv7 – iPhone 3GS, iPhone 4 & iPhone4S
ARMv7s – iPhone 5 & iPhone 5C
ARM64 – iPhone 5S & iPhone 6
In the ARM line of choices, each higher version supports the lower version. e.g. You can compile for ARMv7 and it will run on ARMv7s devices. However, this means it is missing out on any CPU optimizations present in the newer architecture, and may mean your app runs slower. Major performance differences are unlikely, but you can test manually, to see for your app.
In order to get the most support and the best performance, I personally recommend the ARMv7 + ARM64 selection for my apps.
The best way to see all devices and which architecture they use, is the iOS Support Matrix. Here they show you all devices and their ARM Architecture. However in the most recent update, they have moved to showing the processor version, instead of the architecture version, which can make things a little trickier. To see the older version, see iOS Support Matrix 3.2.0.
In Android you need to select the ABI (Application Binary Interface). It is defining the CPU architecture and instruction set. Android comes in a huge array of devices, this can include x86 and ARM based processors. The number of devices is overwhelming and there is no realistic way, to manually check which devices to support. The types of architectures you can build for are:
armeabi – Old devices
armeabi-v7a – Samsung Galaxy S4
arm64-v8a – Samsung Galaxy S7
x86 – Emulators
x86_64 – Emulators, Asus Zenphone 2
In this scenario, it is best to look at popular devices and ensure you have them covered. You will most likely cover many thousands more in the process. There is no official chart on the most popular Android devices, hence you can search for popular devices, and you will come across charts such as the one from AppBrain. They give you an idea of the most popular devices. Samsung and HTC tend to top most charts. Once you find a list of the most popular devices, you can research their specifications, and ensure your app supports the right architecture.
Note: Older ABI’s will run on newer ABI’s, with the ARM options. For example armeabi will run on devices with support for armeabi-v7a. However, this is strongly discouraged, as armeabi will cause unexpected issues on multi-core devices that support armeabi-v7a. armeabi-v7a will run on arm64-v8a CPU’s.
I recommend the armeabi-v7a + x86 selection for Android apps, it covers most devices, while keeping the resulting package size, low.
UWP only has the option of ARM or x86/x64 and the choice here is easy. You pick both, and have all device covered. It will result in a larger binary, but you then have full support on all UWP devices.
Applicable to all platforms, if you want to use a native library in your Xamarin application, you need to make sure your application supports the CPU Architecture in which the native library was compiled. Most natively compiled libraries however, will come with several packages, for each architecture they support. Its important you have the appropriate binary, for each architecture.
The SDK Version is what API’s are available to your app. Different devices, can have different supported SDK’s, and hence this is where you could think of CPU Architecture and SDK’s as two parts of a Venn Diagram, and what overlaps, are the devices you support.
iOS has the highest upgrade percentage of any platform. Within months, well over 90% of iPhone users are at least using one of the 2, latest versions, that their device supports. This is great for app developers, as you have the option to not support somewhat old versions, as the amount of users would be very low. Have a look at the App Store Support for current stats on iOS usage.
iOS simply has a drop down box on what minimum SDK to support, under Deployment Target. I normally choose iOS 8.0.
However, this is different than the SDK Version. This is the version of which the API’s you will get to use.
With this discrepancy, you must now be aware not to call any API’s on SDK’s higher than Version 8.0 unless you first check if it is supported.
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
Android refers to their API’s via Level Numbers, and you have to select the API level for three separate properties.
Compile (Target Framework)
This refers to what API’s your app is expecting to use, when it is compiled. This means that your code is compiled against this version, and you will receive build errors if the API’s you want to use are not available. This does not guarantee that they will be available at runtime, as your app might be installed on a device with a lower SDK installed. This value is used during compilation.
This is the minimum API level that the app will be able to install on. As your Compile (Target Framework) is likely set higher, it will also mean that you may be using API’s that are not available at this level. To ensure your app still runs, any API’s that are not available on this minimum API Level, must be checked at run time before calling.
if ((int)Android.OS.Build.VERSION.SdkInt >= 23)
The Target is where you expect the app to run. Normally you keep this the same as the Compile (Target Framework), as that is what you built your app in, hence you expect it to run on that API level. This value is used at run time, where as the Target Framework is used during Compile.
What Should I Choose?
In Android, the last project I did targeted a minimum of API Level 20. Take into account that this was due to the user base not having very old phones. If you want to see the current versions you may want to support, have a look at Android Dashboards, which shows the usage of each API Level. I normally consider anything around 70% to be a decent user base, but this decision must be made, depending on your user base.
UWP is fairly new, and hence they aren’t many versions. WinRT and Windows 8 Silverlight are considered obsolete and very few people, even bother to develop for this platform anymore. In much the same way as the other platforms, you have a Minimum Version and a Target Version.
The Min Version, is the lowest version of the OS, that it will run on. My recommendation here is 10240, as it is the lowest, and hence full support. The Target Version is what you will compile against and normally you will select the highest level at the moment, which is 15063 (Creators Update).
UWP works a little differently, rather than detecting API numbers to determine features, you look to see if the feature is enabled instead, sometimes at a particular version number. e.g.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract"), 2, 0)
This has given a high level view of CPU Architecture and SDK’s to support for your application. While the file size has always been the main concern with the level of supported devices, Android and iOS both allow ways to reduce the binary to the end users, meaning users will only download the correct binary for their architecture, instead of all architectures. iOS does this by App Thinning by enabling bitcode and Android is doing this via Multi-APK support. Android also has an up and coming technology called Instant Apps.