在上一篇文章從頭開發一個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外掛的目的就是隔離對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實際測試一下。
目前這個外掛還是個簡易版本,未來希望能加上地圖,導航,線路規劃等一系列的功能
專案地址 ,歡迎貢獻程式碼和issue,喜歡可以給個star