從頭開發一個Flutter插件(二)高德地圖定位插件

在上一篇文章從頭開發一個Flutter插件(一)開發流程裏具體介紹了flutter插件的具體開發流程,從建立項目到發佈。接下來將會爲Flutter天氣項目開發一個基於高德定位sdk的flutter定位插件。java

完整代碼在git倉庫裏 github.com/KinsomyJS/l…android

申請key

首先先進入到高德地圖定位sdk文檔內下載定位sdk,並按要求申請app key,這裏很少作介紹,文檔已經很詳細了ios

配置環境

sdk文檔裏一樣有關於配置工程的demo,可是由於flutter 插件項目不是一個android工程,因此會有所區別。大體分如下幾步:git

1.集成遠程依賴

compile 'com.amap.api:location:latest.integration'
複製代碼

2.配置app key

在AndroidManifest.xml的application標籤中配置Key:github

<meta-data android:name="com.amap.api.v2.apikey" android:value="您的Key">
</meta-data>
複製代碼

3.聲明service

在application標籤中聲明service組件:json

<service android:name="com.amap.api.location.APSService"></service>
複製代碼

4.聲明權限

flutter插件的目的就是隔離對sdk native code的實現,讓使用者直接使用dart代碼就能夠得到到sdk提供的定位信息,插件和使用者交互的代碼是在libs下的dart文件中提供的接口。 插件的android文件夾下面是一個完整的android工程結構,咱們在這個工程下完成上述的四步。惟一一點不一樣的是,配置app key利用gradle裏的manifestPlaceholders屬性爲用戶預留,讓用戶本身來填寫。api

因而配置app key改寫成:bash

<meta-data android:name="com.amap.api.v2.apikey" ndroid:value="${LOCATION_APP_KEY}"/>
複製代碼

這個LOCATION_APP_KEY,使用者使用插件的時候在本身flutter項目的android工程下的app/build.gradle文件裏填寫本身申請的高德key便可。app

android {
    compileSdkVersion 27

    lintOptions {
       ...
    }

    defaultConfig {
        ...
        manifestPlaceholders = [
                LOCATION_APP_KEY : "b947abf0a6820efedc65d06428f14281", /// 高德地圖key
        ]
    }
}
複製代碼

到目前爲止,一個基於高德sdk的定位插件工程就算配置好了,下面就是實現部分。ide

實現

flutter 插件最終暴露給插件使用者的是dart代碼的接口,使用者再也不須要關心Android和Ios平臺上的代碼,在定位插件項目中,惟一須要配置的就是上文所說的高德開放平臺的app key.

由於如今是將特定平臺的sdk開發成插件供flutter app使用,其實就能夠理解在Android或者ios平臺正常開發項目,將flutter app須要的數據傳遞過去,flutter插件只是在特定平臺的實現上作了一次封裝與隔離,封裝了dart接口,隔離了兩個不一樣平臺實現的差別。

理解這個概念,寫出一個flutter插件就變得很容易了,dart和java之間的相互通訊在前面寫的一篇文章Flutter探索與實踐Flutter和原生互相通訊一節講述過,這裏就直接上手展現源碼。

Java部分

java部分的代碼寫在了AmapLocationPlugin.java類下面,它分別實現了MethodChannel.MethodCallHandler, EventChannel.StreamHandler。而且在registerWith方法調用的實例化MethodChannel和EventChannel。

final MethodChannel methodChannel = new MethodChannel(registrar.messenger(), "plugin.kinsomy.com/methodchannel");

final EventChannel eventChannel = new EventChannel(registrar.messenger(), "plugin.kinsomy.com/eventchannel");
複製代碼
  • 重寫MethodChannel.MethodCallHandler的onMethodCall方法接受dart代碼的方法調用
@Override
	public void onMethodCall(MethodCall call, Result result) {
		if (call.method.equals("startLocation")) {
			//啓動定位
			mLocationClient.startLocation();
		} else if (call.method.equals("stopLocation")) {
			//中止定位
			mLocationClient.stopLocation();
		} else if (call.method.equals("getLocation")) {
			result.success(mLocation);
		} else {
			result.notImplemented();
		}
	}

複製代碼
  • 重寫EventChannel.StreamHandler的onListen,該方法攜帶了一個EventChannel.EventSink實例,經過該實例對象能夠調用mEventSink.success()向dart傳遞數據流,也就是插件裏的定位信息
@Override
	public void onListen(Object o, EventChannel.EventSink eventSink) {
		this.mEventSink = eventSink;
	}
複製代碼
  • 經過高德sdk的AMapLocationClient獲取到定位信息,並將其封裝成json字符串供dart調用。

dart部分

dart部分的代碼在項目根目錄lib文件夾下的amap_location_plugin.dart文件。

  • 在構造函數裏實例化和java代碼中一樣channel name的MethodChannel與EventChannel
factory AmapLocation() {
    if (_instance == null) {
      final MethodChannel methodChannel =
          const MethodChannel('plugin.kinsomy.com/methodchannel');
      final EventChannel eventChannel =
          const EventChannel('plugin.kinsomy.com/eventchannel');
      _instance = AmapLocation.private(methodChannel, eventChannel);
    }
    return _instance;
  }
複製代碼
  • 提供接口方法開始定位startLocation和對應的中止定位
Future<void> get startLocation =>
      _methodChannel.invokeMethod("startLocation");
複製代碼
  • 實例化Stream接受event返回的定位數據
Stream<String> _onLocationFetched;
_onLocationFetched =
        _eventChannel.receiveBroadcastStream().map((dynamic event) => event);
複製代碼

這樣一個基於高德定位sdk的flutter定位插件就算完成了,在example裏寫一個demo實際測試一下。

目前這個插件仍是個簡易版本,將來但願能加上地圖,導航,線路規劃等一系列的功能

項目地址 ,歡迎貢獻代碼和issue,喜歡能夠給個star

參考文檔

  1. Developing Packages & Plugins

  2. flutter/plugins git倉庫

  3. Dart packages

  4. 深刻理解Flutter Platform Channel

相關文章
相關標籤/搜索