Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set $(SupportedOSPlatformVersion)=24 in Android template #9517

Closed
jonpryor opened this issue Nov 15, 2024 · 0 comments · Fixed by #9656
Closed

Set $(SupportedOSPlatformVersion)=24 in Android template #9517

jonpryor opened this issue Nov 15, 2024 · 0 comments · Fixed by #9656
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects.
Milestone

Comments

@jonpryor
Copy link
Member

jonpryor commented Nov 15, 2024

Context: dotnet/android-libraries#767
Context: dotnet/android-libraries#767 (comment)

For .NET 10, we should update the dotnet new android template so that $(SupportedOSPlatformVersion) is 24, bumping from the current default of 21.

The reason for this is that "desugaring" "moves" Java methods to locations that we don't expect, which can result in AbstractMethodErrors at runtime. Setting the minimum SDK version to >= 24 avoids this desugaring step, preventing the Java methods from being moved in a manner we don't expect, and thus avoiding the AbstractMethodError.

Note that 21 will still be the supported minimum for those that need it, however this will keep most users who do not need to support devices that old from having desugaring issues.

@jonpryor jonpryor added Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned. labels Nov 15, 2024
@jonpryor jonpryor added this to the .NET 10 milestone Nov 15, 2024
@jpobst jpobst removed the needs-triage Issues that need to be assigned. label Nov 15, 2024
jonpryor pushed a commit that referenced this issue Jan 10, 2025
Fixes: #9517

Context: #9527
Context: dotnet/java-interop@1f27ab5
Context: dotnet/android-libraries#767
Context: dotnet/android-libraries#767 (comment)

[Desugaring][0] is an Android SDK build step which rewrites Java
bytecode so that some Java 8+ language constructs can be used on
older Android versions, containing a Dalvik VM that doesn't natively
support those constructs.  The primary examples are interface static
methods and interface default methods, which *moves* methods from the
declaring type to a *different* `$-CC`-suffixed type.

For example, consider
[`ImageAnalysis.Analyzer.getDefaultTargetResolution()`][1], which is
an interface default method:

	// Java
	/* partial */ class ImageAnalysis {
	    /* partial */ interface Analyzer {
	        default Size getDefaultTargetResolution() {…}
	    }
	}

Our bindings for `androidx.camera.core` expect the
`getDefaultTargetResolution()` method to be on `Analyzer`:

	// C#
	[Register("androidx/camera/core/ImageAnalysis$Analyzer", "", "AndroidX.Camera.Core.ImageAnalysis/IAnalyzerInvoker")]
	public partial interface IAnalyzer : IJavaObject, IDisposable, IJavaPeerable {
	    unsafe Size? DefaultTargetResolution
	    {
	        [Register("getDefaultTargetResolution", "()Landroid/util/Size;", "GetGetDefaultTargetResolutionHandler:AndroidX.Camera.Core.ImageAnalysis/IAnalyzer, Xamarin.AndroidX.Camera.Core")]
	        get {
	            return Java.Lang.Object.GetObject<Size>(_members.InstanceMethods.InvokeVirtualObjectMethod("getDefaultTargetResolution.()Landroid/util/Size;", this, null).Handle, JniHandleOwnership.TransferLocalRef);
	        }
	    }
	}

When desugaring is used, the `Analyzer` interface is changed,
moving the default interface method body to a separate type:

	/* partial */ interface Analyzer {
	    Size getDefaultTargetResolution();      // interface declaration
	}
	/* partial */ class Analyzer$-CC {
	    Size getDefaultTargetResolution() {…}   // default implementation
	}

The movement of methods across types breaks our JNI-based bindings,
which don't have easy support for such movements.  The movement of
`getDefaultTargetResolution()` causes C# apps attempting to invoke the
`ImageAnalysis.IAnalyzer.DefaultTargetResolution` property *crash*:

	JNI DETECTED ERROR IN APPLICATION: JNI CallObjectMethodA called with pending exception java.lang.AbstractMethodError: abstract method "android.util.Size androidx.camera.core.ImageAnalysis$Analyzer.getDefaultTargetResolution()"

The workaround is to *not desugar* the app, which can be done by
setting `$(SupportedOSPlatformVersion)`=24, which sets the minimum
supported Android version to Android 7.0, released 2016-Aug-22.

We could fix this, but the fix is only needed for apps which need to
run on Android 6.0 API-23 and earlier devices.  As these devices are
so old, we'd rather focus on more important issues.

Attempt to improve things by updating the `dotnet new android`
template in .NET 10 so that the default
`$(SupportedOSPlatformVersion)` value is 24, up from 21.  This will
avoid the entire desugaring problem for new apps (until they set
`$(SupportedOSPlatformVersion)` to 23 or lower…).

Note that Android 5.0 / API-21 will still be the supported minimum
for those that need it, however this will keep most users who do not
need to support devices that old from having desugaring issues.

[0]: https://developer.android.com/studio/write/java8-support
[1]: https://developer.android.com/reference/androidx/camera/core/ImageAnalysis.Analyzer#getDefaultTargetResolution()
@github-actions github-actions bot locked and limited conversation to collaborators Feb 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App+Library Build Issues when building Library projects or Application projects.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants