在開發一個上線的app過程當中,單純的依賴某一種框架在當前基本不存在,不可避免的須要多種技術參與。php
本文以集成百度地圖爲例,詳細講述如何在flutter中集成android原生模塊,flutter怎麼調用java,以及java如何通知flutter。java
爲何以百度地圖爲例呢,百度地圖含jar和so,比較全面,又是一個視圖型的框架,比較容易看到結果。android
命令行中運行git
flutter create --template=plugin futter_baidu_map
在android-studio打開項目github
文檔地址:api
http://lbsyun.baidu.com/index...android-studio
這裏選擇想要的模塊:app
下載以後是這樣一個結構:框架
所有放到剛纔建立項目的android項目的libs目錄中,這個目錄若是不存在須要建立一下,最後的目錄結構以下:async
修改一下build.gradle,增長依賴
打開FlutterBaiduMapPlugin編輯,初次打開會出現這個提示:
點擊一下右上角的 "Setup SDK",
這裏按需選擇配置,這裏我選擇了Anroid API 27 Platform.
下面編輯咱們想要的功能,這個時候坑來了:
這裏雖然導入了百度地圖的庫,依賴也加了,可是android studio竟然識別不出來!!!!這個問題困擾了我n久,甚至還搞了一套flutter的fake代碼放在其餘項目中。
轉折來了......今天突然發現這裏有個菜單:
點擊一下,android-studio會新開一個項目:
神奇的發現,那些紅色的不能識別的代碼都消失了!!!
繼續往下搞:
按照這裏的指示增長一些配置,申請一個key,這裏就不細說了
http://lbsyun.baidu.com/index...
修改java文件:com.example.flutterbaidumap.FlutterBaiduMapPlugin
public class FlutterBaiduMapPlugin implements MethodCallHandler { private Activity activity; private LocationManager mSysLocManager; public FlutterBaiduMapPlugin(Activity activity) { this.activity = activity; } /** * Plugin registration. */ public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_baidu_map"); channel.setMethodCallHandler(new FlutterBaiduMapPlugin( registrar.activity() )); } @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.equals("init")) { SDKInitializer.initialize(activity.getApplicationContext()); try { if (mSysLocManager == null) { /** 獲取系統的定位服務管理類*/ mSysLocManager = (LocationManager) JNIInitializer.getCachedContext() .getSystemService(Context.LOCATION_SERVICE); } //成功返回true result.success(true); } catch (Exception e) { // 失敗返回false result.success(false ); } } else { result.notImplemented(); } } }
在dart中調用:修改flutter_baidu_map.dart
import 'dart:async'; import 'package:flutter/services.dart'; class FlutterBaiduMap { static const MethodChannel _channel = const MethodChannel('flutter_baidu_map'); static Future<bool> init() async { return await _channel.invokeMethod('init'); } }
在example的main.dart中這麼調用
@override initState() { initBaidu(); super.initState(); } void initBaidu() async{ bool result = await FlutterBaiduMap.init(); if(result){ print("百度地圖加載成功..."); }else{ print("百度地圖加載失敗..."); } }
運行輸出:
java文件增長判斷,並增長一個MethodChannel的引用,向flutter發送消息全靠他了。
package com.example.flutterbaidumap; import android.app.Activity; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Build; import android.os.Bundle; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.PluginRegistry.Registrar; import com.baidu.mapapi.JNIInitializer; import com.baidu.mapapi.SDKInitializer; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * FlutterBaiduMapPlugin */ public class FlutterBaiduMapPlugin implements MethodCallHandler { private Activity activity; private LocationManager mSysLocManager; private MethodChannel channel; public FlutterBaiduMapPlugin(Activity activity,MethodChannel channel) { this.activity = activity; this.channel = channel; } /** * Plugin registration. */ public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_baidu_map"); channel.setMethodCallHandler(new FlutterBaiduMapPlugin(registrar.activity(),channel)); } @Override public void onMethodCall(final MethodCall call, final Result result) { if (call.method.equals("init")) { SDKInitializer.initialize(activity.getApplicationContext()); try { if (mSysLocManager == null) { /** 獲取系統的定位服務管理類*/ mSysLocManager = (LocationManager) JNIInitializer.getCachedContext() .getSystemService(Context.LOCATION_SERVICE); } //成功返回true result.success(true); } catch (Exception e) { // 失敗返回false result.success(false); } } else if (call.method.equals("startLocation")) { mSysLocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener); result.success(true); } else { result.notImplemented(); } } private LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { Map<String,Object> data = new HashMap<String,Object>(); data.put("latitude",location.getLatitude()); data.put("longitude",location.getLongitude()); data.put("result", "onLocationChanged"); channel.invokeMethod("onLocation" ,data ); } @Override public void onStatusChanged(String s, int i, Bundle bundle) { Map<String,Object> data = new HashMap<String,Object>(); data.put("result", "status"); channel.invokeMethod("onLocation" ,data ); } @Override public void onProviderEnabled(String s) { Map<String,Object> data = new HashMap<String,Object>(); data.put("result", "onProviderEnabled"); channel.invokeMethod("onLocation" ,data ); } @Override public void onProviderDisabled(String s) { Map<String,Object> data = new HashMap<String,Object>(); data.put("result", "onProviderDisabled"); channel.invokeMethod("onLocation" ,data ); } }; }
增長調用,修改flutter_baidu_map.dart,這裏須要使用StreamController的add方法增長事件,並使用StreamController的stream增長一個監聽:
static Future<bool> init() async { _channel.setMethodCallHandler(handler); //注意這裏須要設置一下監聽函數 return await _channel.invokeMethod('init'); } static StreamController<Map> _locationUpdateStreamController = new StreamController.broadcast(); static Stream<Map> get locationUpdate=>_locationUpdateStreamController.stream; static Future<dynamic> handler(MethodCall call) { String method = call.method; switch (method) { case "onLocation": { _locationUpdateStreamController.add( call.arguments ); } break; } return new Future.value(""); }
修改main.dart
void initBaidu() async{ bool result = await FlutterBaiduMap.init(); if(result){ print("百度地圖加載成功..."); await FlutterBaiduMap.startLocation(); print("正在監聽..."); //這裏監聽位置改變 FlutterBaiduMap.locationUpdate.listen( (Map data){ print("獲取到百度地圖定位:$data"); }); }else{ print("百度地圖加載失敗..."); } }
輸出:
一種方法是發佈到https://pub.dartlang.org 上去,參考官網指引:https://flutter.io/developing...
另外一種是這邊要講的:本地依賴
把使用flutter_baidu_map模塊的項目放在同一層目錄中(實際上這個也沒有必要),編輯調用方的pubspec.yaml,增長依賴:
沒錯,就這麼簡單,而後在這個項目中運行一下:
flutter package get
而後就能夠愉快的使用了。
一、flutter調用java:
建立plugin,並在java的Plugin實現類中實現onMethodCall方法
二、java調用flutter:
在java中使用MethodChannel調用方法,並在dart中使用StreamController結合StreamController.stream實現監聽。
三、其餘項目使用plugin
編輯pubspec.yaml,增長本地依賴,或者發佈到pub.dartlang.org
https://github.com/jzoom/flut...
若有疑問,請加qq羣854192563討論