4

I have various implementations of a partial class DeviceServices to provide platform specific implementations of certain device or OS specific features for Android, iOS and so on. My app is targeting API level 33.0 and the minimum version is API level 21.0.

Some APIs are specific to certain Android versions and higher, so I want to make sure that they only get called on the supported version. However, I always receive the following warning (and similar ones depending on the API being used):

warning CA1416: This call site is reachable on: 'Android' 21.0 and later. 'WindowInsets.Type.SystemBars()' is only supported on: 'android' 30.0 and later.

The following code to hide and show the system bars works on all my devices and the emulators that I have tried so far, but I am concerned about earlier Android versions. I still receive the warning above with it despite checking for the correct target API version:

static partial class DeviceServices
{
    private static Activity _activity;

    public static void SetActivity(Activity activity)
    {
        _activity = activity;
    }

    public static partial void HideSystemControls()
    {
#if ANDROID30_0_OR_GREATER
       if (Build.VERSION.SdkInt >= BuildVersionCodes.R) //R == API level 30.0
       {
            _activity?.Window?.InsetsController?.Hide(WindowInsets.Type.SystemBars());
       }
#endif
    }

    public static partial void ShowSystemControls()
    {
#if ANDROID30_0_OR_GREATER
       if (Build.VERSION.SdkInt >= BuildVersionCodes.R) //R == API level 30.0
       {
            _activity?.Window?.InsetsController?.Show(WindowInsets.Type.SystemBars());
       }
#endif
    }
}

So, what is the correct way to do this? I'm not sure how to proceed. I've used platform-specific APIs plenty of times and never had any problems with it before, but this warning concerns me. I had a look at the support article about this warning already, too, but I didn't find it very helpful: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416. I also don't want to suppress the warnings. Maybe I am missing something here or can I simply ignore the warning in this case?

Update:

I am using Visual Studio 2022 17.4 Preview 2.1 and .NET 7.0 RC1.

I have also tried calling the APIs directly from within the MainActivity, but keep receiving the same warnings after a rebuild.

Update 2:

Here is a sample repository where the problem can be reproduced, just uncomment the following code block in the MainActivity.cs file:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        
//#if ANDROID30_0_OR_GREATER
//        if (Build.VERSION.SdkInt >= BuildVersionCodes.R) //R == API level 30.0
//        {
//            Window?.InsetsController?.Hide(WindowInsets.Type.SystemBars());
//        }
//#endif
    }
Julian
  • 5,290
  • 1
  • 17
  • 40
  • 1
    You have to check the api level at runtime. #if is **compile** time – Jason Oct 22 '22 at 17:36
  • Yes, I'm aware that preprocessor directives are compile time checks. That's why I also tried the second approach, but it didn't help, either. – Julian Oct 22 '22 at 17:38
  • Your 2nd example is still wrapped in an #if – Jason Oct 22 '22 at 17:40
  • I've updated the question. I also receive the warning without the #if. That's why I tried adding that. When it's compiled against API 29 or less, it shouldn't even show up in the MSIL code, right? – Julian Oct 22 '22 at 17:43
  • 1
    is there an actual problem you're trying to fix, or are you just trying to address the warning message? I suspect the compiler simply isn't "smart" enough to recognize that the suspect code is wrapped in an check for the API level – Jason Oct 22 '22 at 19:00
  • @Jason I want to avoid that the warning actually becomes a problem. There is probably a good reason for it and I haven't had this problem before when checking for the API level. – Julian Oct 24 '22 at 06:37

3 Answers3

7

Use OperatingSystem.IsAndroidVersionAtLeast, instead of Build.VERSION.SdkInt. Like this:

if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
    _activity?.Window?.InsetsController?.Hide(WindowInsets.Type.SystemBars());
}

You should get no warnings after this.

More documentation is here: https://learn.microsoft.com/en-us/dotnet/api/system.operatingsystem.isandroidversionatleast

PEK
  • 3,688
  • 2
  • 31
  • 49
  • Thanks, for the proposed solution. I managed to solve it using `Microsoft.Maui.ApplicationModel.Platform.CurrentActivity` in my Android-specific class. – Julian Nov 14 '22 at 12:31
1

At first, I created a new sample and added the code you provided in the MainActivity, there is no any warning message. So you can also have a try.

And then, I created a new class just like you did, there was also no any warning. And the Composition of the solution:

  1. Visual Studio 2022 17.4 preview 2.1
  2. add <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" android:maxSdkVersion="33"/> this in the AndroidManifest.xml
  3. In my project's build settings file, the Android Target FrameWork is Android api 31.

In addition, for the android part in the maui, there is only one Activity nameed MainActivity which is inherited from the AppCompactActivity. So you don't need to declare the static partial class DeviceServices for android, you can just do this in the mainactivity. Furthermore, the Activity and the AppCompactActivity are not same.

Liyun Zhang - MSFT
  • 8,271
  • 1
  • 2
  • 14
  • Thank you for your answer. Unfortunately, that doesn't solve the problem for me. I've added the `` to my AndroidManifest.xml and the warning still shows up. The `DeviceServices` are required in my scenario as I am not calling the the APIs from within the `MainActivity` but from the code behind of my Views, so that's on purpose and is unrelated to the problem at hand, AFAIK. Changing from `Activity` to `MainActivity` doesn't make a difference here, but is a good idea. The API calls work, I'm just concerned about the warnings. – Julian Oct 24 '22 at 07:22
  • You can try to update the Visual Studio or create a new project to test, this warning never appear in my project. @ewerspej – Liyun Zhang - MSFT Oct 24 '22 at 07:32
  • And when you try the code in the mainactivity, did you get the warning? @ewerspej – Liyun Zhang - MSFT Oct 24 '22 at 07:37
  • Yes I do. I just updated the question with that information. – Julian Oct 24 '22 at 07:37
  • I'll try to reproduce the issue with a new solution. – Julian Oct 24 '22 at 07:38
  • Did you get the warning in the new solution? @ewerspej – Liyun Zhang - MSFT Oct 24 '22 at 07:52
  • Yes, in a different solution, I get the same problem. I reused a small and recently created solution instead of an entirely new one, but it should suffice. I have added a link to the repo to the question. – Julian Oct 24 '22 at 07:55
  • Although this doesn't directly solve the issue. your hint about `Activity` and `AppCompatActivity` (or even `MauiActivity`) not being the same got me thinking. I dug a little deeper and found out that those are not even related inheritance-wise. Instead, a conversion takes place during the assignment (probably using the `explicit` operator). Therefore, I switched to using `Microsoft.Maui.ApplicationModel.Platform.CurrentActivity` which solved the issue – Julian Nov 14 '22 at 12:34
0

I've tested with different Android emulators and API versions now and so far, there is no actual problem despite the warnings. It seems they are false flags, possibly because the runtime checks are not evaluated by the compiler. Since I don't want to disable the warnings explicitly, I will just have to ignore them for now.

UPDATE

I've removed the SetActivity() and switched to using Microsoft.Maui.ApplicationModel.Platform.CurrentActivity and now the warnings are gone:

using AndroidPlatform = Microsoft.Maui.ApplicationModel.Platform;

static partial class DeviceServices
{
    public static partial void HideSystemControls()
    {
       if (Build.VERSION.SdkInt >= BuildVersionCodes.R) //R == API level 30.0
       {
            AndroidPlatform.CurrentActivity?.Window?.InsetsController?.Hide(WindowInsets.Type.SystemBars());
       }
    }
}
Julian
  • 5,290
  • 1
  • 17
  • 40