.NET MAUI:如何确保 Android 平台特定代码只在支持的 Android 版本上执行?

4

我有多种partial class DeviceServices的实现,为Android、iOS等平台提供某些设备或操作系统特定功能的特定实现。我的应用程序针对API级别33.0进行定位,最低版本是API级别21.0。

某些API仅适用于某些较高的Android版本,因此我希望确保它们仅在支持的版本上调用。然而,无论使用何种API(取决于正在使用的API),我总是收到以下警告:

警告CA1416:此调用站点在可达的版本“Android” 21.0及更高版本上可达。“WindowInsets.Type.SystemBars()”仅支持“android” 30.0及更高版本。

以下代码可在所有我尝试过的设备和仿真器上隐藏和显示系统栏,但我担心早期的Android版本。尽管检查了正确的目标API版本,但我仍然收到上述警告:

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
    }
}

那么,正确的方法是什么?我不确定该如何继续。我以前多次使用特定于平台的API,并且从未遇到任何问题,但这个警告让我担忧。我已经查看了有关此警告的支持文章,但我并没有觉得它很有用:https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416。我也不想抑制警告。也许我在这里漏掉了什么,或者在这种情况下我可以简单地忽略警告吗?
更新:
我正在使用Visual Studio 2022 17.4 Preview 2.1和.NET 7.0 RC1。
我还尝试直接从MainActivity中调用API,但在重新构建后仍然收到相同的警告。
第二次更新: 这里是一个示例存储库,可以重现该问题,只需取消注释MainActivity.cs文件中的以下代码块:
    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
    }

1
你必须在运行时检查API级别。#if是编译时间。 - Jason
是的,我知道预处理器指令是编译时检查。这就是为什么我也尝试了第二种方法,但它也没有帮助。 - Julian
您的第二个示例仍然被包含在#if中。 - Jason
我已更新问题。即使没有#if,我也收到了警告。这就是为什么我尝试添加它的原因。当针对API 29或更低版本进行编译时,它甚至不应该出现在MSIL代码中,对吧? - Julian
1
你是在尝试解决一个实际的问题,还是只是想解决警告信息?我怀疑编译器并不“聪明”到能够识别可疑代码已经包含了对API级别的检查。 - Jason
@Jason 我想避免这个警告成为实际问题。这可能有很好的理由,而且在检查 API 级别时我以前没有遇到过这个问题。 - Julian
3个回答

8

感谢您提供的解决方案。我在我的 Android 特定类中使用了 Microsoft.Maui.ApplicationModel.Platform.CurrentActivity 来解决它。 - Julian

1

首先,我创建了一个新的示例,并在MainActivity中添加了您提供的代码,没有任何警告信息。所以您也可以尝试一下。

接着,我创建了一个新的类,就像您所做的那样,也没有任何警告。解决方案的组成如下:

  1. Visual Studio 2022 17.4 预览版 2.1
  2. 在AndroidManifest.xml文件中添加以下内容:<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" android:maxSdkVersion="33"/>
  3. 在项目的构建设置文件中,Android目标框架为Android API 31。

此外,在maui中与android相关的部分只有一个名为MainActivity的Activity,它继承自AppCompactActivity。因此,您不需要为android声明static partial class DeviceServices,可以直接在MainActivity中处理。此外,ActivityAppCompactActivity是不同的。


谢谢您的回答。不幸的是,这对我来说并不能解决问题。我已经在我的AndroidManifest.xml文件中添加了<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />,但是警告仍然出现。在我的情况下,DeviceServices是必需的,因为我不是从MainActivity中调用API,而是从我的视图的代码后台调用,所以这是有意的,与手头的问题无关。将Activity改为MainActivity在这里没有任何区别,但这是一个好主意。API调用可以工作,我只是担心这些警告。 - Julian
你可以尝试更新Visual Studio或者创建一个新的项目来进行测试,这个警告在我的项目中没有出现过。@ewerspej - Liyun Zhang - MSFT
当您在MainActivity中尝试运行该代码时,是否收到了警告?@ewerspej - Liyun Zhang - MSFT
我会尝试使用新的解决方案来重现这个问题。 - Julian
是的,在另一个解决方案中,我遇到了同样的问题。我重用了一个小而最近创建的解决方案,而不是完全新的解决方案,但应该足够了。我已经在问题中添加了一个存储库链接。 - Julian
显示剩余3条评论

0

我已经测试了不同的Android模拟器和API版本,到目前为止,尽管有警告,但实际上没有任何问题。看起来它们是虚假警报,可能是因为编译器没有评估运行时检查。由于我不想显式禁用警告,所以现在只能忽略它们。

更新

我已经删除了SetActivity()并改用Microsoft.Maui.ApplicationModel.Platform.CurrentActivity,现在警告已经消失:

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());
       }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接