preface

In the process of developing an online APP, it is almost impossible to rely solely on a certain framework at present, which inevitably requires the participation of multiple technologies.

This article uses Baidu Map integration as an example to describe how to integrate Android native modules into Flutter, how Flutter calls Java, and how Java informs Flutter.

Why take Baidu Map as an example? Baidu Map contains JAR and SO, which is relatively comprehensive and a view-based framework, making it easier to see the results.

Create a Plugin

Run from the command line

flutter create --template=plugin futter_baidu_map 
Copy the code

Open the project in Android-Studio

Integrate android version according to baidu Map official document

Document Address:

http://lbsyun.baidu.com/index.php?title=androidsdk/guide/create-project/ak

Select the desired module here:

After downloading, there is a structure like this:

Put them all into the libs directory of the Android project that you created just now. If this directory does not exist, you need to create it. The final directory structure is as follows:

4071650091-5b17c0ba3d00d_articlex.png

Modify build.gradle to add dependencies

1524805254-5b17bf215a515_articlex.png

Open the FlutterBaiduMapPlugin edit and the first time you open it you will get this prompt:

3967820436-5b17bf6e93291_articlex.png

Click on the “Setup SDK” in the upper right corner,

1436375478-5b17bfa31bd94_articlex.png

Here you choose the configuration on demand, and here I chose the Anroid API 27 Platform.

Let’s edit the feature we want, and this is when the pit comes:

3953759209-5b17d2b16342c_articlex.png

Although the library of Baidu Map has been imported here, the dependency has also been added, but Android Studio can not recognize !!!! I had this problem for so long that I even made a fake code for Flutter for other projects.

The twist comes…… Today I found a menu:

1444258350-5b17da130025a_articlex.png

One click and android-Studio will open a new project:

84776404-5b17da66db281_articlex.png

Amazing discovery, those red unrecognized codes are gone!! !

Keep going:

Integrated location function

In accordance with the instructions to add some configuration, apply for a key, here don’t dwell on the http://lbsyun.baidu.com/index.php?title=androidsdk/guide/create-project/hellomap

Initialize map SDK(flutter call Java)_

Modify the Java file: 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) {/ * * get location-based services system management class * / mSysLocManager = (LocationManager) JNIInitializer. GetCachedContext () .getSystemService(Context.LOCATION_SERVICE); } // Successful returntrue
        result.success(true); } catch (Exception e) {// Failure is returnedfalse
        result.success(false); }}else{ result.notImplemented(); }}}Copy the code

Dart: Modify 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'); }}Copy the code

Dart in example

 @override
  initState() {

    initBaidu();

    super.initState();
  }

  void initBaidu() async{
    bool result = await FlutterBaiduMap.init();
    if(result){
      print("Baidu Map loaded successfully...");
    }else{
      print("Baidu Map loading failed..."); }}Copy the code

Run output:

238120750-5b1801e106aa6_articlex.png

Listen for location (Java notification flutter)

The Java file adds judgments and adds a reference to MethodChannel, which is up to it to send messages to 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) {/ * * get location-based services system management class * / mSysLocManager = (LocationManager) JNIInitializer. GetCachedContext () .getSystemService(Context.LOCATION_SERVICE); } // Successful returntrue
                result.success(true); } catch (Exception e) {// Failure is returnedfalse
                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 ); }}; }Copy the code

Dart = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController = StreamController

static Future<bool> init() async { _channel.setMethodCallHandler(handler); // Note that we need to set up the listener function herereturn 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("");
  }
Copy the code

Modify the main dart

void initBaidu() async{
    bool result = await FlutterBaiduMap.init();
    if(result){
      print("Baidu Map loaded successfully...");

     await FlutterBaiduMap.startLocation();
      print("Listening in..."); / / here listening position change FlutterBaiduMap. LocationUpdate. Listen ((Map data) {print("Get baidu map location:$data");
      });

    }else{
      print("Baidu Map loading failed..."); }}Copy the code

Output:

Other projects use this module:

A kind of method is published to the https://pub.dartlang.org, and refer to the website instructions: https://flutter.io/developing-packages/#publish

The other is the one I’m talking about here: local dependencies

To put the projects using the Flutter_baidu_map module in the same layer directory (which is actually unnecessary), edit the callers’ pubspec.yaml to add dependencies:

Yes, that’s it, and then run it in this project:

flutter package get 
Copy the code

Then it can be used happily.

To sum up:

1, Flutter calls Java:

Create the plugin and implement the onMethodCall method in Java’s Plugin implementation class

Java calls flutter:

Methods are called in Java using MethodChannel and listened in DART using StreamController in conjunction with streamController.stream implementation.

3. Other projects use plugin to edit pubspec.yaml, add local dependencies, or publish to pub.dartlang.org

Code:

https://github.com/jzoom/flutter-example/tree/master/flutter_baidu_map