做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)

我们已经介绍了如何通过 .NET 绑定 iOS 原?库 ,本篇开始介绍?下如何通过 .NET 绑定 Android 原?库。
Android 的库 Android 的库以 .jar 做打包, 通过?具你可以将多个 .jar 完成绑定,然后通过 C# 调?原?的 Java 库。对?起 iOS , Android 的库绑定简单很多。
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

从上图可以看到 Xamarin.Android / .NET for Android 通过使?托管可调?包装器 (MCW) 实现绑定。MCW 是?个 JNI 桥,在托管代码需要调? Java 代码时会使?它。托管可调?包装器还?持对 Java 类型进??类 化以及覆盖 Java 类型的虚拟?法。同样,每当 Android 运?时 (ART) 代码需要调?托管代码时,它都会通 过另?个称为 Android 可调?包装器 (ACW) 的 JNI 桥来实现。
创建?个 Android 原?库绑定项?
通过命令?创建?个 Android 原?库绑定项?d

otnet new android-bindinglib -o Droid.AMap

进?该项?我们看看?件结构
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

项???有 Transforms ?件夹有对应的三个 xml ?件,分别是 EnumFields.xml ,EnumMethods.xml , Metadata.xml , 各?作?如下 :
  • MetaData.xml – 允许对最终 API 进?更改,例如更改?成的绑定的命名空间。
  • EnumFields.xml – 包含 Java int 常量与 C# enums 之间的映射。
  • EnumMethods.xml – 允许将?法参数和返回类型从 Java int 常量更改为 C# enums
其中 MetaData.xml ?件是这些?件中的最常?的导?,因为它允许对绑定进??般?途的更改,例如:重命名命名空间、类、?法或字段,使其遵循 .NET 约定。
删除不需要的命名空间、类、?法或字段。
将类移到不同的命名空间。
添加其他?持类以使绑定的设计遵循 .NET 框架模式。
▌把 jar ?件添加到绑定项? 在项?中添加 Jars ?录 ,把?德地图的 jar 包添加到该?录下 ,并把 arm64-v8a ,armeabi-v7a ,x86_64 这三个?录添加进来
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

添加完成后,修改 .csproj ?件
net6.0-android 21 enable enable

这样就把项?添加好了,没有像 iOS 原?库绑定那么繁琐。然后编译?下 ,凡尔赛 + 星??海了
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

排雷工作 看?这么多错,真的要考虑?下是不是放弃,其实这也?常治愈,我们逐个来排雷。
  • 'PoiCreator' does not implement interface member 'IParcelableCreator.NewArray(int)'.
  • 'PoiCreator.NewArray(int)' cannot implement 'IParcelableCreator.NewArray(int)'
    错误对应的是这个?法 ,实际就是返回类型出错了,我们先根据源?件看看 path 路径就可以解决
// Metadata.xml XPath method reference: path="/api/package[@name='com.amap.api.maps.model']/class[@name='PoiCreato r']/method[@name='newArray' and count(parameter)=1 and parameter[1] [@type='int']]" [Register ("newArray", "(I)[Lcom/amap/api/maps/model/Poi; ", "GetNewArray_IHandler")] public virtual unsafe global::Com.Amap.Api.Maps.Model.Poi[]? NewArray (int p0) { const string __id = "newArray.(I)[Lcom/amap/api/maps/model/Poi; "; try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (p0); var __rm = _members.InstanceMethods.InvokeVirtualObjectMethod (__id, this, __args); return (global::Com.Amap.Api.Maps.Model.Poi[]?) JNIEnv.GetArray (__rm.Handle, JniHandleOwnership.TransferLocalRef, typeof (global::Com.Amap.Api.Maps.Model.Poi)); } finally { }}

【做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)】确认好后,需要在 Metadata.xml 做添加
Java.Lang.Object[]

  • The type 'AMap' already contains a definition for 'MarkerDragEnd'
这个是重复定义导致的,只需要添加如下代码删除就可以了,如

  • 'BusLineSearch': member names cannot be the same as their enclosing type
重命名导致的错误 ,把名字修改?下即可,如
AmapBusLineSearch

  • cannot change access modifiers when overriding 'protected'
重载的时候出现权限问题,这个时候你需要的是把权限修正好,如
protected

解决上述的所有问题,基本上就可以治愈了,当编译通过?刻你会?常兴奋
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

找个 .NET for Android 项?看看 做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

  • ?家可以去我的 GitHub 下载该示例
Android 的原?绑定? iOS 的简单得多,所以更容易??。希望各位?伙伴能多动?,有时候也是?个很好的体验。经过学习,相信?家也掌握了如何? .NET 绑定 iOS 和 Android 的原?库了。
我们知道 MAUI 是开发跨平台应?的解决?案 ,? C# 可以直接把 iOS , Android , Windows , macOS , Linux ,Tizen 等应?开发出来。那我们在这个框架除了?底层?定义的 UI 控件外,如果我们要?如?德地图这样的 第三?控件,要如何做呢?接下来我就和?家介绍?下。
如果你还没有学习原?库绑定的知识,可以到以下链接学习相关内容:
  • 关于做?个?德地图的 iOS / Android MAUI 控件(iOS 原?库绑定)
  • 做?个?德地图的 iOS / Android MAUI 控件(Android 原?库绑定)
在上?两个例?中我们学习到把原??德的 iOS / Android SDK 绑定,也? .NET for iOS 和 .NET for Android 进?了调?。但要? MAUI 就意味着调??式改变, ?次性编写多平台使?。要实现这个效果,先看看 MAUI 的基础架构。
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

我们可以清楚看到, MAUI 除了公?的 xmal ?件外, 实际上也把特定平台的?些设定放置到 Platforms 的?件夹内, Platforms 的??件夹就是对应的平台。我们知道可以根据不同平台去渲染平台界?。这就是我们 常说的?定义平台控件了。
在前?部分我们也提到了 MAUI 采? Handler 模式去设定平台界?。如果我们要实现?个?德地图的 MAUI 控件,具体的架构是这样的
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

我们需要去创建如上图的?个结构,我们需要为 AMap 添加?个共享?件 AMap.shared.cs ,这个?件 AMapHandler 继? ViewHandler。
public interface IAMap : IView { } public class AMap : View, IAMap { } partial class AMapHandler { public static IPropertyMapper MapMapper = new PropertyMapper(ViewHandler.ViewMapper) { }; public AMapHandler() : base(MapMapper) { } }

然后在 Platforms 下的 Android 和 iOS ?件夹添加各?的平台 AMap 调??法。
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

为 AMap.Android.cs 添加 Android 环境下?德地图的渲染?式
namespace AMap.UI.Apps { public partial class AMapHandler : ViewHandler { private AMapHelper _mapHelper; private MapView mapView; internal static Bundle Bundle { get; set; } public AMapHandler(IPropertyMapper mapper, CommandMapper commandMapper = null) : base(mapper, commandMapper) { } protected override MapView CreatePlatformView() { mapView = new Com.Amap.Api.Maps.MapView(Context); 03.UIControls.md 7/5/2022 4 / 8 return mapView; } protected override void ConnectHandler(MapView platformView) { base.ConnectHandler(platformView); AMapLocationClient.UpdatePrivacyAgree(Context, true); AMapLocationClient.UpdatePrivacyShow(Context, true, true); _mapHelper = new AMapHelper(Bundle, platformView); mapView = _mapHelper.CallCreateMap(); } } class AMapHelper : Java.Lang.Object { private Bundle _bundle; private MapView _mapView; public event EventHandler MapIsReady; public MapView Map { get; set; } public AMapHelper(Bundle bundle, MapView mapView) { _bundle = bundle; _mapView = mapView; } public MapView CallCreateMap() { ? _mapView.OnCreate(_bundle); return _mapView; } } }

为 AMap.iOS.cs 添加 iOS 环境下?德地图的渲染?式
namespace AMap.UI.Apps { public partial class AMapHandler : ViewHandler { public AMapHandler(IPropertyMapper mapper, CommandMapper commandMapper = null) : base(mapper, commandMapper) { } protected override MAMapView CreatePlatformView() { MAMapView.UpdatePrivacyShow(AMapPrivacyShowStatus.DidShow, AMapPrivacyInfoStatus.DidContain); MAMapView.UpdatePrivacyAgree(AMapPrivacyAgreeStatus.DidAgree); AMapServices.SharedServices.ApiKey = ""; AMapServices.SharedServices.EnableHTTPS = true; //try //{ MAMapView map = new MAMapView(); map.SetShowsUserLocation(true); map.SetUserTrackingMode(MAUserTrackingMode.Follow); return map; } protected override void ConnectHandler(MAMapView PlatformView) { } protected override void DisconnectHandler(MAMapView PlatformView) { if (PlatformView.Delegate != null) { PlatformView.Delegate.Dispose(); PlatformView.Delegate = null; } PlatformView.RemoveFromSuperview(); } } }

这?我们要修改 MAUI 的项??件,这?有?个设定需要注意的
  1. 因为这个控件只是针对 iOS / Android 两个平台,所以我们只保留 net6.0-android 和 net6.0-ios
  2. ?德 SDK 运?建议在真机下使?,特别是 iOS ,需要制定版本号,还有编译环境,我的环境是在 Apple silicon 下所以也要设定好 RuntimeIdentifier,还有就是编译的时候,我花了特别多时间在这?, ?家可以参考我这个在 GitHub 上?问?答的 Issue
    https://github.com/xamarin/xa... macios/issues/15372
ios-arm64 true 4 SdkOnly 13.0 true true true true true true true

3. 记得按照平台引?原?库的绑定

  • 查看完整项??件,请点击该链接
  • 也别忘记去把?些平台特有的设定设置好,具体可以 iOS 设定请点击该链接
  • Android 设定请点击该链接
最后?步就是在 MauiProgram.cs 上注册
builder .UseMauiApp() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }) .ConfigureMauiHandlers(handlers => { handlers.AddHandler(typeof(AMap), typeof(AMapHandler)); });

选择编译运?就可以看到?德地图终于可以在 MAUI 环境下跑起来了
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

小结 对于很多?来说或者都是初步接触了 MAUI ,实际上要做好多平台的兼容还要有?常?的路要?。希望通过这个系列的?章,能给?些第三??商和开发者?些帮助,能尽快提供 MAUI 的?持。这样才能为这个新的技术注?活?。
相关资料:
  • .通过 Microsoft Docs 了解MAUI
  • 通过 Microsoft Learn 学习MAUI
  • 使??德地图 SDK for Android 请访问
  • 了解 Android 原?库绑定的内容,请访问
  • 学习 ViewHandler ?定义 MAUI组件 请点击访问该链接
做?个?德地图的|做?个?德地图的 iOS / Android MAUI 控件(下)
文章图片

长按识别二维码
关注微软中国MSDN
点击了解MAUI~

    推荐阅读