在开发一个上线的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讨论