flutter怎样集成原生模块android版,以及现阶段会遇到的坑和解决方法

news/2024/6/19 23:32:53

前言

在开发一个上线的app过程中,单纯的依赖某一种框架在当前基本不存在,不可避免的需要多种技术参与。

本文以集成百度地图为例,详细讲述如何在flutter中集成android原生模块,flutter怎么调用java,以及java如何通知flutter。

为什么以百度地图为例呢,百度地图含jar和so,比较全面,又是一个视图型的框架,比较容易看到结果。

创建一个plugin

命令行中运行

flutter create --template=plugin futter_baidu_map 

在android-studio打开项目

按照百度地图官方文档集成android版本

文档地址:

http://lbsyun.baidu.com/index...

这里选择想要的模块:

下载之后是这样一个结构:

clipboard.png

全部放到刚才创建项目的android项目的libs目录中,这个目录如果不存在需要创建一下,最后的目录结构如下:

clipboard.png

修改一下build.gradle,增加依赖

clipboard.png

打开FlutterBaiduMapPlugin编辑,初次打开会出现这个提示:

clipboard.png

点击一下右上角的 "Setup SDK",

clipboard.png

这里按需选择配置,这里我选择了Anroid API 27 Platform.

下面编辑我们想要的功能,这个时候坑来了:

这里虽然导入了百度地图的库,依赖也加了,但是android studio居然识别不出来!!!!这个问题困扰了我n久,甚至还搞了一套flutter的fake代码放在其他项目中。

转折来了......今天忽然发现这里有个菜单:

点击一下,android-studio会新开一个项目:

神奇的发现,那些红色的不能识别的代码都消失了!!!

继续往下搞:

集成定位功能

按照这里的指示增加一些配置,申请一个key,这里就不细说了
http://lbsyun.baidu.com/index...

初始化地图SDK(flutter调用java)_

修改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通知flutter)

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 

然后就可以愉快的使用了。

总结一下:

1、flutter调用java:

创建plugin,并在java的Plugin实现类中实现onMethodCall方法

2、java调用flutter:

在java中使用MethodChannel调用方法,并在dart中使用StreamController结合StreamController.stream实现监听。

3、其他项目使用plugin
编辑pubspec.yaml,增加本地依赖,或者发布到pub.dartlang.org

代码:

https://github.com/jzoom/flut...

如有疑问,请加qq群854192563讨论


http://www.niftyadmin.cn/n/1895021.html

相关文章

事件(响应用户的操作)

每个事件处理函数&#xff0c;都可以接收一个event对象作为参数&#xff0c;这个对象里面包含这次用户操作的丰富信息。 <button οnclick"buttonClickHandler(event)">点我试试</button> <script> function buttonClickHandler(event) {     …

冒泡排序法_冒泡排序算法

在日常开发中经常会遇到一类问题&#xff0c;就是对一个集合的数据进行排序掌握一些排序算法&#xff0c;对于日常开发是非常有帮助的今天介绍一下冒泡排序法算法逻辑时间复杂度由上图逻辑可以得出&#xff0c;冒泡排序的循环次数为由循环次数可以得出&#xff0c;冒泡排序的时…

辗除法求最大公约数_用欧几里得算法求最大公约数

12 和 18 的最大公约数是多少&#xff1f;最大公约数&#xff1a;最大公约数&#xff0c;也称最大公因数、最大公因子&#xff0c;指两个或多个整数共有约数中最大的一个。例如&#xff1a;18 与 12 的最大公约数为 6 。短除法短除法是求最大公因数的一种方法&#xff1a;先把每…

canal mysql从库_Canal 实现 Mysql数据库实时数据同步

简介1.1 canal介绍​ Canal是一个基于MySQL二进制日志的高性能数据同步系统。Canal广泛用于阿里巴巴集团(包括https://www.taobao.com)&#xff0c;以提供可靠的低延迟增量数据管道&#xff0c;github地址&#xff1a;https://github.com/alibaba/canalCanal Server能够解析MyS…

模型剪枝和量化_人脸识别系统之模型压缩裁剪量化

本文用途仅仅是在前人经验下&#xff0c;自我总结&#xff0c;以供以后学习使用&#xff0c;若有错误&#xff0c;敬请您批评指正。应用背景&#xff1a;深度学习的应用加速了计算机视觉领域的发展&#xff0c;但是随着模型深度的加深&#xff0c;也带来了高额的存储空间、计算…

代码生成器开发笔记(2)-数据库架构

代码生成器开发笔记(&#xff12;)&#xff0d;数据库架构 程序 2009-06-13 01:30:01 阅读55 评论0 字号&#xff1a;大中小 订阅 要完成代码生成器&#xff0c;第一个要解决的是完全解析数据库架构。 对SQL Server当然没什么问题&#xff0c;早在ADO时代就可以通过查询sy…

mysql on linux 安装_MySQL on Linux手动安装方法

MySQL on Linux手动安装方法发布时间:2007-06-05 11:44:45来源:红联作者:TecCTO1. 下载"mysql-standard-5.0.27-Linux-i686-icc-glibc23.tar.gz"&#xff0c;推荐ICC版本&#xff0c;据称比GCC性能提高10-20%2. 复制到/usr/local/&#xff0c;解压&#xff1a;tar zx…

MongoDB最新最佳连接工具:Robo 3T

MongoDB连接工具 像使用Mysql&#xff0c;喜欢用Navicat连接工具一样。 在使用MongoDB数据库的时候&#xff0c;同样可以使用Robo 3T图形化工具。 一、下载Robo 3T Robo 3T官网 Studio 3T&#xff1a;专业人士使用的&#xff0c;需要付费。 Robo 3T&#xff1a;虽然免费&…