AndroidX icon indicating copy to clipboard operation
AndroidX copied to clipboard

Nullability on returned types from Builders does not match Android API docs and @NotNull annotations

Open Cheesebaron opened this issue 11 months ago • 5 comments

Android framework version

net9.0-android

Affected platform version

N/A

Description

When using some types from the AndroidX packages, I started noticing a lot of method are returning nullable types, while the Android API docs state that they should not be and are annotated with @NonNull.

I noticed in after updating Xamarin.AndroidX.AppCompat to version 1.7.0.6 that all the methods in NotificationCompat.Builder return nullable types.

So building now looks like this:

var builder = new NotificationCompat.Builder(this, ChannelName);
-builder.SetContentTitle("Title")
+builder.SetContentTitle("Title")?
-    .SetSmallIcon(Resource.Drawable.ic_bar_chart_24)
+    .SetSmallIcon(Resource.Drawable.ic_bar_chart_24)?
-    .SetPriority(NotificationCompat.PriorityLow)
+    .SetPriority(NotificationCompat.PriorityLow)?
-    .SetWhen(0)
+    .SetWhen(0)?
-    .SetOnlyAlertOnce(true)
+    .SetOnlyAlertOnce(true)?
-    .SetContentIntent(pendingIntent)
+    .SetContentIntent(pendingIntent)?
-    .SetOngoing(true)
+    .SetOngoing(true)?
-    .SetColor(ResourcesCompat.GetColor(Resources, Resource.Color.tm_orange, Theme));
return builder.Build();

Looking at for instance SetContentTitle this one is explicitly annotated with @NonNull for its return type. This can be seen here: https://developer.android.com/reference/androidx/core/app/NotificationCompat.Builder#setContentText(java.lang.CharSequence)

Image

The exposed C# API looks like this for the same method, where nullability on return type does not match:

// Metadata.xml XPath method reference: path="/api/package[@name='androidx.core.app']/class[@name='NotificationCompat.Builder']/method[@name='setContentTitle' and count(parameter)=1 and parameter[1][@type='java.lang.CharSequence']]"
[Register ("setContentTitle", "(Ljava/lang/CharSequence;)Landroidx/core/app/NotificationCompat$Builder;", "GetSetContentTitle_Ljava_lang_CharSequence_Handler")]
public virtual unsafe global::AndroidX.Core.App.NotificationCompat.Builder? SetContentTitle (global::Java.Lang.ICharSequence? title)

Steps to Reproduce

  1. Install Xamarin.AndroidX.AppCompat
  2. Use builder APIs as described above

Did you find any workaround?

Add nullability checks all over the place :'( Or downgrade to previous version of AppCompat package

Relevant log output


Cheesebaron avatar May 06 '25 06:05 Cheesebaron

It looks like the actual package for the referenced API is Xamarin.AndroidX.Core.

Looking at Google's androidx.core:core 1.15.0.aar, the methods are correctly annotated:

Image

However if we look at Google's androidx.core:core 1.16.0.aar, the annotations are missing:

Image

According to their release notes they switched to a new system of "Null" annotations, but I am not seeing them anywhere in the .aar file.

jpobst avatar May 06 '25 17:05 jpobst

Oh, OK. So this is not an issue here I guess. Thanks for clearing this up

Cheesebaron avatar May 07 '25 08:05 Cheesebaron

Interestingly when looking at AndroidX.Core 1.16.0 using Android Studio you see:

Image

Cheesebaron avatar May 07 '25 11:05 Cheesebaron

Also noticed this when upgrading to Xamarin.AndroidX.Core 1.16.0.1. Luckily for us we can use 1.15.0.2 to avoid null checks all over the place.

mathiasi avatar May 12 '25 10:05 mathiasi

Opened issue for our tooling to support these new JSpecify annotations: https://github.com/dotnet/java-interop/issues/1335.

jpobst avatar May 12 '25 23:05 jpobst