Maui集成Google Maps遇HandlerNotFoundException及跨平台兼容问题
问题描述
在.NET Maui应用中集成onion.Maui.GoogleMaps包后,仅Android和iOS平台可正常构建运行,MacCatalyst等其他平台会触发错误:
错误详情
Microsoft.Maui.Platform.HandlerNotFoundException: Handler not found for view Maui.GoogleMaps.Map.
Source: Microsoft.Maui
StackTrace:
at Microsoft.Maui.Platform.ElementExtensions.ToHandler(IElement view, IMauiContext context) in D:\a_work\1\s\src\Core\src\Platform\ElementExtensions.cs:line 92
at Microsoft.Maui.Platform.ElementExtensions.ToPlatform(IElement view, IMauiContext context) in D:\a_work\1\s\src\Core\src\Platform\ElementExtensions.cs:line 127
at Microsoft.Maui.Handlers.ContentViewHandler.UpdateContent(IContentViewHandler handler) in D:\a_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 44
at Microsoft.Maui.Handlers.ContentViewHandler.MapContent(IContentViewHandler handler, IContentView page) in D:\a_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 49
at Microsoft.Maui.PropertyMapper2.<>c__DisplayClass5_0[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.IContentViewHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v) in D:\a_work\1\s\src\Core\src\PropertyMapper.cs:line 172 at Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView) in D:\a_work\1\s\src\Core\src\PropertyMapper.cs:line 47 at Microsoft.Maui.PropertyMapper.UpdateProperties(IElementHandler viewHandler, IElement virtualView) in D:\a_work\1\s\src\Core\src\PropertyMapper.cs:line 82 at Microsoft.Maui.Handlers.ElementHandler.SetVirtualView(IElement view) in D:\a_work\1\s\src\Core\src\Handlers\Element\ElementHandler.cs:line 79 at Microsoft.Maui.Handlers.ViewHandler.SetVirtualView(IElement element) in D:\a_work\1\s\src\Core\src\Handlers\View\ViewHandler.cs:line 129 at Microsoft.Maui.Handlers.ViewHandler2[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.ContentViewGroup, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IView view) in D:\a_work\1\s\src\Core\src\Handlers\View\ViewHandlerOfT.cs:line 53
at Microsoft.Maui.Handlers.ContentViewHandler.SetVirtualView(IView view) in D:\a_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 27
at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.ContentViewGroup, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IElement view) in D:\a_work\1\s\src\Core\src\Handlers\View\ViewHandlerOfT.cs:line 56
at Microsoft.Maui.Controls.Element.SetHandler(IElementHandler newHandler) in D:\a_work\1\s\src\Controls\src\Core\HandlerImpl\Element\Element.Impl.cs:line 69
at Microsoft.Maui.Controls.Element.set_Handler(IElementHandler value) in D:\a_work\1\s\src\Controls\src\Core\HandlerImpl\Element\Element.Impl.cs:line 19
at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IElement.set_Handler(IElementHandler value) in D:\a_work\1\s\src\Controls\src\Core\HandlerImpl\VisualElement\VisualElement.Impl.cs:line 308
at Microsoft.Maui.Platform.ElementExtensions.ToHandler(IElement view, IMauiContext context) in D:\a_work\1\s\src\Core\src\Platform\ElementExtensions.cs:line 96
at Microsoft.Maui.Platform.ElementExtensions.ToPlatform(IElement view, IMauiContext context) in D:\a_work\1\s\src\Core\src\Platform\ElementExtensions.cs:line 127
at Microsoft.Maui.Platform.ScopedFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) in D:\a_work\1\s\src\Core\src\Platform\Android\Navigation\ScopedFragment.cs:line 22
at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState) in C:\a_work\1\s\generated\androidx.fragment.fragment\obj\Release\net6.0-android\generated\src\AndroidX.Fragment.App.Fragment.cs:line 2031
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 352
已通过Program.cs的条件编译#if ANDROID || IOS规避部分错误,但需解决XAML及代码后台的兼容问题,同时希望限定项目仅针对Android和iOS开发。
解决方案
一、XAML及代码后台的跨平台兼容处理
1. XAML:通过OnPlatform条件渲染控件
使用OnPlatform在Android/iOS显示地图,其他平台显示替代内容:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:maps="clr-namespace:Maui.GoogleMaps;assembly=Maui.GoogleMaps" x:Class="MauiApp1.NewPage3" Title="NewPage3"> <ContentView> <OnPlatform x:TypeArguments="View"> <!-- Android和iOS加载地图控件 --> <On Platform="Android, iOS"> <maps:Map x:Name="mymap" VerticalOptions="FillAndExpand" /> </On> <!-- 其他平台显示提示文本 --> <On Platform="MacCatalyst, Windows"> <Label Text="该功能仅支持Android和iOS平台" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </On> </OnPlatform> </ContentView> </ContentPage>
2. 代码后台:条件编译隔离地图相关逻辑
用#if ANDROID || IOS包裹所有地图相关代码,避免非支持平台编译报错:
#if ANDROID || IOS using Maui.GoogleMaps; #endif namespace MauiApp1; public partial class NewPage3 : ContentPage { public NewPage3() { InitializeComponent(); #if ANDROID || IOS // 仅在支持平台执行地图初始化逻辑 mymap.MoveToRegion(MapSpan.FromCenterAndRadius( new Position(37.79752, -122.40183), Distance.FromMiles(1))); #endif } }
二、限定项目仅针对Android和iOS开发
1. Visual Studio图形界面操作
- 右键项目 → 属性
- 切换到「目标框架」选项卡
- 在「目标平台」列表中取消勾选MacCatalyst、Windows等非必要平台
- 保存设置,项目将自动移除对应平台配置
2. 手动编辑.csproj文件
打开项目的.csproj文件,修改<TargetFrameworks>节点,仅保留Android和iOS:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net8.0-android;net8.0-ios</TargetFrameworks> <UseMaui>true</UseMaui> <!-- 其他项目配置 --> </PropertyGroup> <!-- 其他项目内容 --> </Project>
修改后项目仅针对Android和iOS编译,不会触发其他平台的handler缺失错误。
内容的提问来源于stack exchange,提问作者the_yaz2000

