1. 江湖人士首页
  2. IT江湖
  3. 猿在江湖

Xamarin.Forms 使用高德地图SDK,5分钟教程

Xamarin.Forms 使用高德地图SDK(更新,支持nuget分包安装),高德地图SDK在原生Android方面,提供定制下载与使用gradle从Maven或JCenter集成使用,介绍客户端代码(Xamarin APP)调用SDK时Xamarin.Android与Xamarin.Forms协调交互的方式。

Xamarin.Forms 使用高德地图SDK

效果视频:

Xamarin.Forms 使用高德地图SDK

高德地图SDK版本

3DMap-7.4.0-地图

Location-4.9.0-位置

Navi-3DMap-7.4.0-导航与地图

Search-7.3.0-搜索

Track-Track1.3.0Location4.9.0-猎鹰与位置

教程

(详细代码解释参看文章底部阅读原文)

1.Xamarin项目Android端安装安卓nuget包(支持按需求分包安装)

*注Navi-3DMap与3DMap不能同时安装,因为导航sdk已经含有地图sdk

Track与Loaction不能同时安装,因为猎鹰sdk已经含有位置sdk

Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Location -Version 4.9.0<br>Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Search -Version 7.3.0<br>Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Track -Version 1.3.0<br>Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.3DMap -Version 7.4.0<br>Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Navi3DMap -Version 7.4.0

2.参考高德地图sdk文档配置Xamarin.Android/Properties/AndroidManifest.xml文件的key与权限,SDK用法对照调用C#相应函数;

3.在Xamarin方面将高德地图相关控件使用Renderer方案在Xamarin.Forms显示;

4.涉及Xamarin.FormsXamarin.Android的layout.xml以及Renderer的使用时,可以参考源码示例的代码进行相应处理。(涉及Android的Inflate函数相关知识)

5.涉及Xamarin.Forms、Xamarin.Android间消息的通讯可以参考源码示例,使用Xamarin.Forms提供的MessagingCenter处理。(涉及消息发布订阅相关知识)

其它资料

Xamarin.Forms 演示高德地图SDK的Sample源码:

https://github.com/jingliancui/XamarinFormsAMapSDKSample

原生Android的高德地图SDK的使用方法:

https://lbs.amap.com/

微软官方Renderer教程示例:

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/video-player/

Xamarin.Forms消息发布与订阅教程

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/messaging-center

消息发布与订阅教程

教程:

发布消息

Xamarin.Forms.MessagingCenter.Send

消息订阅

Xamarin.Forms.MessagingCenter.Subscribe

取消消息订阅

Xamarin.Forms.MessagingCenter.Unsubscribe

tips:

注意renderer进行pub/sub的时候要进行相关的unsubscribe,否则app会crash

后话:

Xamarin.Forms库本身已经带有支持消息发布订阅模式(Pub/Sub)的实现了。

一个比较正常的用法是直接在share层(.Net Standard引用了Xamarin.Forms的一层)内进行业务开发,那传递参数的类型都可以是各种类,如.net standard类或者forms的ui类。

另外一个场景是,当我们在进行层与层之间的消息触发的时候,需要注意使用通用的类,比如object、string、int等元类,也可以用自定义类,注意不要使用native独有的类即可,因为假设我们的解决方案是Xamarin.Forms+iOS+Android,每一个native层特有的原生类是Share层没有的,例如需要iOS的NSString数据发送到.Net Standard,因为.Net Standard是没有mono的NSString的。这时候可能会想到让.Net Standard层引用native层达到两层的类都共用,但ide会报错不能互相套娃,因为native层已经引用.Net Standard层了。

另外一个需要注意的是教程提到renderer内使用pub/sub注意的事项。

Xamarin.Forms使用Pub/Sub发布订阅进行native层与share层的通讯

Xamarin.Forms 使用高德地图SDK
Xamarin.Forms 使用高德地图SDK

Part 1 高德地图SDK与Nuget相关的资料

高德地图SDK在原生Android方面,提供定制下载与使用gradle从Maven或JCenter集成使用,定制下载的方式浏览这个网址:相关下载-Android 地图SDK | 高德地图API,使用gradle集成的方式浏览这个网址:Android Studio 配置工程-创建工程-开发指南-Android 地图SDK

定制下载的方式是开发者勾选需要集成的功能后,高德的网站自动将选择的功能合成一个jar包或aar包,而gradle集成的方式像Nuget安装库一样,安装开发者自己选择的库。在高德SDK没有支持gradle集成前只能使用前者,而前者的缺点就是当所有包分开完成绑定工作后,在App端编译会遇到api冲突的异常。而gradle方式则没有这种问题。

不过要注意的是导航SDK已经包含了地图SDK、猎鹰SDK已经包含了定位SDK;所以导航SDK与地图SDK不能同时集成在APP中,只能两者选一;猎鹰SDK与定位SDK不能同时集成在APP中只能两者选一。

Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Location -Version 4.9.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Search -Version 7.3.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Track -Version 1.3.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.3DMap -Version 7.4.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Navi3DMap -Version 7.4.0

Part 2 调用SDK时Xamarin.Android与Xamarin.Forms协调交互的方式

  • 代码项目层级关系
Xamarin.Forms 使用高德地图SDK
Xamarin.Forms 使用高德地图SDK

SampleApp这一层其实是.Net Standard类库,而SampleApp.Android这一层则可以看作是main函数所在的一层,通常会把这一层叫做native层。查看native层的Reference会看到它引用了SampleApp这一层,记住这个层级关系有利于分清楚集成第三方SDK与层级调用的关系。

而熟悉.Net Core开发工作的开发者就比较熟悉.Net Standard的作用–跨平台,所以.Net Standard支持的像一系列异步接口、HttpClient、System.Text.Json等这些常用的功能也能直接或通过Nuget安装的方式使用。

但是要注意的是,也因为.Net Standard的跨平台性质,不要将native层的类放到.Net Standard中,例如Android Native的Android.App.Activity类。因为Xamarin.Android能引用.Net Standard,那其他native层如Xamarin.iOS、UWP、WPF也能引用。

所以很多入门Xamarin的开发者的一个问题是Forms的东西怎么在Android或者iOS显示,Android或者iOS的东西怎么在Forms显示。下文讲到的Renderer与MessagingCenter就是其中的两个解决方案。

  • 集成SDK

示例代码中包含了全功能的演示,所以引用了导航SDK(含地图SDK)、猎鹰SDK(含位置SDK)与搜索SDK

Xamarin.Forms 使用高德地图SDK,5分钟教程 1
Xamarin.Forms 使用高德地图SDK

根据高德官方文档配置key和配置权限这两节教程,配置native层Properties/AndroidManifest.xml文件即可

  • Renderer

界面控件在Android中可以通过xml或者代码创建:

MapView:

mapView = new MapView(this);

AMapNaviView:

   <com.amap.api.navi.AMapNaviView
        android:id="@+id/navi_view"
                         android:layout_width="match_parent"
                         android:layout_height="match_parent"/>

而Xamarin开发需要将这些原生的控件显示到Forms层中,就可以用到Renderer方案,重点是要在override的OnElementChanged函数中将控件设值。

 protected override void OnElementChanged(ElementChangedEventArgs<XAMapNaviView> e)
        {
            mRelativeLayout = (Context as MainActivity).naviRelativeLayout;
            (Context as MainActivity).navi.StartNavi(NaviType.Emulator);
            SetNativeControl(mRelativeLayout);
        }

以上代码中没有使用基类提供的Inflate函数去获取xml的控件,而是放在MainActivity中使用Inflate获取,是因为SDK中的控件需要进行生命周期管理。一般情况下没有生命周期管理的控件都可以在Renderer中使用Inflate函数获取。

  • MessagingCenter

除了原生控件需要在Forms层显示,还需要数据在Forms层与Native层间互相传递,协调代码工作。

这里以高德SDK中查询天气数据为案例进行讲解。

熟悉WPF或者UWP开发工作的.Net开发者比较熟悉以下Forms层中的Xaml代码

<StackLayout>
            <Label Text="其他数据搜索功能请参照官方文档自行实现"></Label>
            <Label Text="本示例只作天气查询演示"></Label>
            <Button Text="Weather Query" x:Name="WeatherBtn" Clicked="WeatherBtn_Clicked"></Button>
            <Label Text="北京天气"></Label>
            <Label x:Name="ReportTimeLabel"></Label>
            <Label x:Name="WeatherLabel"></Label>
            <Label x:Name="TemperatureLabel"></Label>
            <Label x:Name="WindDirectionLabel"></Label>
            <Label x:Name="WindPowerLabel"></Label>
            <Label x:Name="HumidityLabel"></Label>
        </StackLayout>

用户点击Button,触发了这个Button的Clicked事件

public const string QueryWeather = "QueryWeather";
        private void WeatherBtn_Clicked(object sender, EventArgs e)
        {
            MessagingCenter.Send(new object(), QueryWeather);
        }

而事件函数的函数体内只是使用了MessagingCenter的Send函数

Xamarin.Forms 使用高德地图SDK,5分钟教程 2
消息的引用

通过查找QueryWeather常量的引用可以看到,消息从SampleApp层Send,在SampleApp.Android层Subscribe

这就是MessagingCenter的用法,MessagingCenter是Pub/Sub设计模式(发布订阅设计模式)的一种实现的类。

订阅了这个消息的native层,在forms层发布消息的时候就会收到触发调用的通知。

继续将业务往下发展

MessagingCenter.Subscribe<object>(this, SearchPage.QueryWeather, sender =>
            {
                //检索参数为城市和天气类型,实况天气为WEATHER_TYPE_LIVE、天气预报为WEATHER_TYPE_FORECAST
                var mquery = new WeatherSearchQuery("北京", WeatherSearchQuery.WeatherTypeLive);
                var mweathersearch = new WeatherSearch(this);
                mweathersearch.SetOnWeatherSearchListener(new OnWeatherSearchListener());
                mweathersearch.Query=mquery;
                mweathersearch.SearchWeatherAsyn(); //异步搜索 
            });

当订阅者收到通知后触发查询天气的函数(高德SDK查询天气相关的函数)

查询天气的函数执行成功或者失败后,都会触发OnWeatherSearchListener类内的回调函数OnWeatherLiveSearched

如果天气查询成功了可以使用MessagingCenter将天气数据打包后发送回给forms层,为什么是打包后发送而不是将高德sdk的result变量发送呢,因为高德sdk的result变量不是跨平台的,是不存在于.Net Standard中的,是带有java平台相关的类或者成员的。

所以我们可以像服务器开发工作一般的处理方法一样,使用DTO(data transfer object)传递数据,DTO在这里就只是.Net Standard中的一个自定义类

 public class WeatherModel
    {
        public string ReportTime { get; set; }
        public string Weather { get; set; }
        public string Temperature { get; set; }
        public string WindDirection { get; set; }
        public string WindPower { get; set; }
        public string Humidity { get; set; }
    }
var weatherlive = weatherLiveResult.LiveResult;
                    var model = new WeatherModel 
                    {
                        ReportTime= weatherlive.ReportTime,
                        Humidity= weatherlive.Humidity,
                        Temperature= weatherlive.Temperature,
                        Weather= weatherlive.Weather,
                        WindDirection= weatherlive.WindDirection,
                        WindPower= weatherlive.WindPower
                    };

                    //发回给forms层
                    MessagingCenter.Send(new object(), SearchPage.QueryWeatherOk, model);

再通过查找QueryWeatherOK常量的引用,这时会看到接收者就是Sample.App层,而发送者就是Sample.Android层

Xamarin.Forms 使用高德地图SDK,5分钟教程 3
数据回发到Forms层

最后在Forms层将数据设置到Xaml中的Label控件完成整个天气的查询业务

 protected override void OnAppearing()
        {
            MessagingCenter.Subscribe<object, WeatherModel>(this, QueryWeatherOk, (sender, args) => 
            {
                Xamarin.Essentials.MainThread.BeginInvokeOnMainThread(() => 
                {
                    ReportTimeLabel.Text = $"{args.ReportTime}发布";
                    WeatherLabel.Text = args.Weather;
                    TemperatureLabel.Text = $"{args.Temperature}°";
                    WindDirectionLabel.Text = $"吹{args.WindDirection}风";
                    WindPowerLabel.Text = $"风力{args.WindPower}级";
                    HumidityLabel.Text = $"湿度{args.Humidity}";
                });
            });
        }

总结一下整个代码的流程如下图,Forms层发送消息,Native层订阅消息后查询天气,天气查询的回调函数将结果回发到Forms层,Forms层通过UI控件显示数据。

Xamarin.Forms 使用高德地图SDK,5分钟教程 4
查询天气序列图

App代码参看:https://github.com/jingliancui/XamarinFormsAMapSDKSample

后记

对比之前转换的全功能的包整体太大,会导致有些不会被用到的库也会添加到代码项目中,现在使用gradle的包进行重新的转换工作,开发者可以根据项目的需求下载对应的nuget包进行安装使用了。

本文综合微信公众号移动开发和人工智能、知乎文章。

知乎原文:https://zhuanlan.zhihu.com/p/139712723

本站最新优惠

Namesilo优惠:新用户省 $1 域名注册-优惠码:45D%UYTcxYuCloZ 国外最便宜域名!点击了解更多

特别优惠:免费赠送 $100 Vultr主机-限时优惠!英文站必备海外服务器!点击了解更多

VPS优惠:搬瓦工优惠码:BWH3OGRI2BMW 最高省5.83%打开外面世界的一款主机点击了解更多

本文来自投稿作者:IT菜鸟,不代表江湖人士立场,如若转载,请注明出处:https://jhrs.com/2020/37306.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

2 × 4 =