Xamarin and Nuget

Xamarin Forms is a complex tool. Not only does it translate from C#/MSIL to platform specific binaries, binaries for iOS or ART for Android, it also has to provide access to other native libraries, both system and 3rd party. This is done by wrapping the binaries in C# accessible code and marshalling types and calls between the C# runtime and native libraries. This sometimes results in large dependency trees of various nuget packages as one package depends on another, which depends on another, and so on. Or, particular native libraries have similar dependencies with other native libraries. For example, Xamarin Forms on Android requires various Google Play Services packages. The underlying Google Play Services libraries depend may depend on other Google Android libraries such as AppCompat. Other nuget packages will have their own similar dependency trees, such as any of the Xamarin Plugins for location, permissions, messaging, etc.

The correct set of versions is stipulated by each package, specifying the required dependencies and allowed range of versions. Once the tree is established, the nuget package manager protects the user by disallowing addition or updates of packages with incompatible versions. Most of the time this is the right thing to do. However, there are a couple of situations where this can become a headache.

Situation 1: Implicit Nuget Package Versions.

If a nuget package requires another one, that package may be included implicitly. As of nuget 2.7, implicit permission in on by default. This means that when a package is added via the nuget package manager, it may automatically and silently pulls in other nuget packages.

If the implicitly required package version is incompatible with already included nuget versions, addition of the new package will fail, or result in strange compilation errors such as these:

The above errors was when trying to add Xamarin Forms Maps 2.5 to an Xamarin Forms 2.5 Android project, with Xamarin.GooglePlayServices.* packages version 60+. The solution is to explicitly include the otherwise implicitly dependent nuget package with the right version. In this case Xamarin.GooglePlayService.Maps

Then the Xamarin Forms Maps project can be built properly.

Situation 2: Downgrading Interdependent Package Groups

When a dependency predecessor needs to be downgraded to accommodate a different nuget package that needs to be added can fail if downgrading violates dependency version stipulations for other nuget packages, even if they can call be downgraded in a compatible way, it will fail:

This is because other existing nuget packages depend on AppCompat with a higher version. Downgrading Google Play Services Base fails the version check for the other packages, so the downgrade is disallowed.

The solution is to uninstall the entire dependency subtree, and re-add with the desired versions.

Lastly, Visual Studio, and the Xamarin Build process perform a great deal of caching. Sometimes nuget changes will fail, or builds will fail after nuget changes, but work after exiting and restarting Visual Studio.

If you have any questions, feel free to contact me at curtis@saltydogtechnology.com