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

kinsomy發表於2019-03-03

在上一篇文章從頭開發一個Flutter外掛(一)開發流程裡具體介紹了flutter外掛的具體開發流程,從建立專案到釋出。接下來將會為Flutter天氣專案開發一個基於高德定位sdk的flutter定位外掛。

完整程式碼在git倉庫裡 github.com/KinsomyJS/l…

申請key

首先先進入到高德地圖定位sdk文件內下載定位sdk,並按要求申請app key,這裡不多做介紹,文件已經很詳細了

配置環境

sdk文件裡同樣有關於配置工程的demo,但是因為flutter 外掛專案不是一個android工程,所以會有所區別。大致分以下幾步:

1.整合遠端依賴

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

2.配置app key

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

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

3.宣告service

在application標籤中宣告service元件:

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

4.宣告許可權

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

flutter外掛的目的就是隔離對sdk native code的實現,讓使用者直接使用dart程式碼就可以獲得到sdk提供的定位資訊,外掛和使用者互動的程式碼是在libs下的dart檔案中提供的介面。 外掛的android資料夾下面是一個完整的android工程結構,我們在這個工程下完成上述的四步。唯一一點不同的是,配置app key利用gradle裡的manifestPlaceholders屬性為使用者預留,讓使用者自己來填寫。

於是配置app key改寫成:

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

這個LOCATION_APP_KEY,使用者使用外掛的時候在自己flutter專案的android工程下的app/build.gradle檔案裡填寫自己申請的高德key即可。

android {
    compileSdkVersion 27

    lintOptions {
       ...
    }

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

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

實現

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實際測試一下。

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

目前這個外掛還是個簡易版本,未來希望能加上地圖,導航,線路規劃等一系列的功能

專案地址 ,歡迎貢獻程式碼和issue,喜歡可以給個star

參考文件

  1. Developing Packages & Plugins

  2. flutter/plugins git倉庫

  3. Dart packages

  4. 深入理解Flutter Platform Channel

相關文章