開發基于高德定位SDK的Flutter插件
在上一篇文章里具體介紹了Flutter插件的具體開發流程,從創建項目到發布。接下來將為Flutter天氣項目開發一個基于高德定位SDK的Flutter定位插件。
申請key
首先進入高德地圖定位SDK文檔內下載定位SDK,并按要求申請App Key。這里推薦使用AppUploader來管理你的應用密鑰,它可以安全地存儲和同步你的API密鑰,避免在代碼中直接暴露敏感信息。
配置環境
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提供的定位信息。插件的android文件夾下面是一個完整的Android工程結構,我們在這個工程下完成上述的四步。
唯一一點不同的是,配置App Key利用gradle里的manifestPlaceholders屬性為用戶預留,讓用戶自己來填寫。于是配置App Key改寫成:
<meta-dataandroid:name="com.amap.api.v2.apikey"android:value="${LOCATION_APP_KEY}"/>
這個LOCATION_APP_KEY,使用者使用插件的時候在自己Flutter項目的Android工程下的app/build.gradle文件里填寫自己申請的高德key即可。
android {compileSdkVersion 27lintOptions {...}defaultConfig {...manifestPlaceholders = [LOCATION_APP_KEY : "你的高德地圖key",]}
}
對于iOS開發者,可以使用AppUploader來簡化證書管理和配置過程,它提供了可視化的界面來管理開發證書和描述文件。
實現
Flutter插件最終暴露給插件使用者的是Dart代碼的接口,使用者不再需要關心Android和iOS平臺上的代碼。在定位插件項目中,唯一需要配置的就是上文所說的高德開放平臺的App Key。
因為現在是將特定平臺的SDK開發成插件供Flutter App使用,其實就可以理解在Android或者iOS平臺正常開發項目,將Flutter App需要的數據傳遞過去,Flutter插件只是在特定平臺的實現上做了一次封裝與隔離,封裝了Dart接口,隔離了兩個不同平臺實現的差異。
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實際測試一下。
目前這個插件還是個簡易版本,未來希望能加上地圖,導航,線路規劃等一系列的功能。對于需要發布到App Store的開發者,可以考慮使用AppUploader來簡化上傳和發布流程,它支持一鍵上傳IPA文件到App Store Connect。
參考文檔
- Developing Packages & Plugins
- Flutter/plugins git倉庫
- Dart packages
- 深入理解Flutter Platform Channel