Bug 25495 - No way of determining at compile time if API calls satisfy the Manifest minSdkVersion
Summary: No way of determining at compile time if API calls satisfy the Manifest minSd...
Status: RESOLVED ANSWERED
Alias: None
Product: Android
Classification: Xamarin
Component: MSBuild ()
Version: 4.18.1
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2014-12-18 08:23 UTC by steven.mark.ford.dev
Modified: 2014-12-18 09:05 UTC (History)
1 user (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED ANSWERED

Description steven.mark.ford.dev 2014-12-18 08:23:08 UTC
List does not understand Android callable wrappers invocation and hence cannot work against Xamarin Generated Android Code. e.g. n_onCreate (p0);

There are obviously small subsets of the output which Lint does understand but the Lint tool is pretty much useless

This makes Android development extremely difficult forcing a developer to have to look up every single Android API call to ensure it meets the android:minSdkVersion="10" specified in the manifest (this is usually picked up automatically by Lint).
Comment 1 steven.mark.ford.dev 2014-12-18 08:24:54 UTC
"*Lint does not understand Android callable wrappers"
Comment 2 Jonathan Pryor 2014-12-18 09:05:40 UTC
> This makes Android development extremely difficult forcing a developer to have
> to look up every single Android API call to ensure it meets the
> android:minSdkVersion="10" specified in the manifest

Add a separate (manual) compilation step.

Xamarin.Android provides a set of Mono.Android.dll assemblies, one per supported API level, which exposes only the types and members present in that API level and lower. The Mono.Android.dll used is specified by $(TargetFrameworkVersion), which is also the *default* android:targetSdkVersion value.

However, just because that's the default behavior doesn't mean it's what you want/need.

What you can instead do is set your $(TargetFrameworkVersion) to your minSdkVersion value, and provide a different value for your targetSdkVersion value. This will ensure that you only use types and members present in the minSdkVersion setting.

However, this can be limiting, in that you may want to "opt-in" into using types and members only present in API levels higher than your minSdkVersion value.

To (somewhat sanely) support this, what you can do is *manually* set $(TargetFrameworkVersion) to the minSdkVersion value, build, and ensure that everything you use is present in minSdkVersion. If you use something that *isn't* present, the build will fail. What you then do is wrap these "errors" in a `#if __ANDROID_X__` block *and* a runtime check:

https://github.com/xamarin/monodroid-samples/blob/ab11d30126549fa39466444767e3ee2286645519/SanityTests/Hello.cs#L284-296
#if __ANDROID_11__
	if (((int)Android.OS.Build.VERSION.SdkInt) >= 11) {

		// Android 11+ _really_ doesn't want you to do networking from the main thread:
		//   http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
		// I want to do so, so...
		var policy = new Android.OS.StrictMode.ThreadPolicy.Builder ()
			.PermitAll()
			.Build ();
		Android.OS.StrictMode.SetThreadPolicy (policy);
	}
#endif  // __ANDROID_11__

The `#if` check will "fix" your compilation error when $(TargetFrameworkVersion)==minSdkVersion. The runtime check is so that when your $(TargetFrameworkVersion) is greater than your minSdkVersion and you run on a device running minSdkVersion, you won't inadvertently invoke methods that don't exist in minSdkVersion.

This could probably be done in an automated form on your continuous integration server -- just use `msbuild /t:Build /p:TargetFrameworkVersion=@minSdkVerion@` -- but it can also be done manually for single builds as well.