Flutter集成高德导航SDK(Android篇)(JAVA语法)

news2024/11/18 7:44:09

先上flutter doctor:
flutter sdk版本为:3.19.4
在这里插入图片描述

引入依赖:
在app的build.gradle下,添加如下依赖:

    implementation 'com.amap.api:navi-3dmap:10.0.700_3dmap10.0.700'

navi-3dmap里面包含了定位功能,地图功能,所以引入这一个包就行

1.在项目的android-app-src-包名 路径下,新建一个class,起名为:AMapNaviPlugin,
AMapNaviPlugin代码如下:



import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;

import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Poi;
import com.amap.api.navi.AMapNavi;
import com.amap.api.navi.AmapNaviPage;
import com.amap.api.navi.AmapNaviParams;
import com.amap.api.navi.AmapNaviType;
import com.amap.api.navi.AmapPageType;
import com.amap.api.navi.INaviInfoCallback;
import com.amap.api.navi.NaviSetting;
import com.amap.api.navi.model.AMapNaviLocation;

import java.util.HashMap;
import java.util.Map;



import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

public class AMapNaviPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
    private static MethodChannel channel;

    private static Context mContext = null;
    //通讯名称,回到手机桌面
    private static String CHANNEL = "com.kdcf.channel/aMapNavi";

    private Activity activity;

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
        if (null == mContext) {
            mContext = binding.getApplicationContext();
        }
        initMethodChannel(binding.getBinaryMessenger());
    }

    private void initMethodChannel(BinaryMessenger binaryMessenger) {
        if (null == binaryMessenger) {
            return;
        }

        channel = new MethodChannel(binaryMessenger, CHANNEL);
        channel.setMethodCallHandler(this);
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        channel.setMethodCallHandler(null);
        channel = null;
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        if (mContext == null) {
            result.error("-1", "context is null", null);
        }

        if (call.method.equals(NaviConstant.START_NAVI)) {
            try {
                Object arguments = call.arguments;
                Map<String,Object> map= (Map<String, Object>) arguments;
                Double endLongitude= (Double) map.get("endLongitude");
                Double endLatitude= (Double) map.get("endLatitude");
                String endPlaceName= (String) map.get("endPlaceName");
                String endPoiId= (String) map.get("endPoiId");

                Map<String,Object> extraParams= (Map<String, Object>) map.get("extraParams");

                Log.e("AMapNaviPlugin","endLongitude:"+endLongitude);
                Log.e("AMapNaviPlugin","endLatitude:"+endLatitude);
                Log.e("AMapNaviPlugin","endPlaceName:"+endPlaceName);
                Log.e("AMapNaviPlugin","endPoiId:"+endPoiId);
                Log.e("AMapNaviPlugin","extraParams参数如下:");
                for (Map.Entry<String, Object> entry : extraParams.entrySet()) {
                    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
                }


                startNavi(endLongitude,endLatitude,endPlaceName,endPoiId,extraParams);
            } catch (Exception e) {
                Log.e("AMapNaviPlugin","异常:"+e.toString());
                result.error("ERROR","AMapNaviPlugin onMethodCall startNavi出错:"+e.toString(),null);
            }
            result.success(200);
        }else if (call.method.equals(NaviConstant.AGREE_PRIVACY)) {
            try {
                NaviSetting.updatePrivacyShow(mContext, true, true);
                NaviSetting.updatePrivacyAgree(mContext, true);
            } catch (Exception e) {
                Log.e("AMapNaviPlugin",e.toString());
                result.error("ERROR","AMapNaviPlugin onMethodCall agreePrivacy出错:"+e.toString(),null);
            }
            result.success(200);
        }else if (call.method.equals(NaviConstant.CANCEL_NAVI)) {
            try {
                AMapNavi.getInstance(mContext).playTTS("导航已结束",true);
                //退出导航组件
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        // 这里是延时后需要执行的代码
                        //退出导航组件
                        AmapNaviPage.getInstance().exitRouteActivity();
                    }
                }, 5000);
            } catch (Exception e) {
                Log.e("AMapNaviPlugin",e.toString());
                result.error("ERROR","AMapNaviPlugin onMethodCall CANCEL_NAVI出错:"+e.toString(),null);
            }
            result.success(200);
        }
    }

    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        activity = binding.getActivity();
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {

    }

    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {

    }

    @Override
    public void onDetachedFromActivity() {

    }

    void startNavi(Double endLongitude,Double endLatitude,String endPlaceName,String endPoiId,Map<String,Object> extraParams){
        //起点
//        Poi start = new Poi("北京首都机场", new LatLng(40.080525,116.603039), "B000A28DAE");
//途经点
//        List<Poi> poiList = new ArrayList();
//        poiList.add(new Poi("故宫", new LatLng(39.918058,116.397026), "B000A8UIN8"));
//终点
        Poi end = new Poi(endPlaceName, new LatLng(endLatitude,endLongitude),endPoiId);
// 组件参数配置
        AmapNaviParams params = new AmapNaviParams(null, null, end, AmapNaviType.DRIVER, AmapPageType.NAVI);
// 启动组件
        AmapNaviPage.getInstance().showRouteActivity(mContext.getApplicationContext(), params, new NaviInfoCallback(mContext,channel,extraParams));
    }
}


新建NaviConstant类,代码如下:

public class NaviConstant {
    //开始导航,flutter向原生传值
    public static String START_NAVI="startNavi";
    //同意隐私政策,flutter向原生传值
    public static String AGREE_PRIVACY="agreePrivacy";

    //到达目的地,原生向flutter传值
    public static String ARRIVE_Destination="arriveDestination";
    //取消导航
    public static String CANCEL_NAVI="cancelNavi";
}

新建NaviInfoCallback类,代码如下:

package com.daohe.kdchufadriver.navi;

import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.view.View;

import com.amap.api.navi.INaviInfoCallback;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.AmapNaviPage;

import java.util.HashMap;
import java.util.Map;

import io.flutter.plugin.common.MethodChannel;

public class NaviInfoCallback implements INaviInfoCallback {
    Context context;
    MethodChannel channel;
    Map<String,Object> extraParams;

    public NaviInfoCallback(Context context,MethodChannel channel,Map<String,Object> extraParams) {
        this.context=context;
        this.channel=channel;
        this.extraParams=extraParams;
    }

    @Override
    public void onInitNaviFailure() {
        Log.e("NaviInfoCallback","onInitNaviFailure");
    }

    @Override
    public void onGetNavigationText(String s) {
        Log.e("onGetNavigationText","onGetNavigationText:"+s);

        // //模拟到达终点
//        Map<String,Object> result=new HashMap<>();
//        result.put("result",extraParams);
//        channel.invokeMethod(NaviConstant.ARRIVE_Destination,result);
//        //退出导航组件
//        Handler handler = new Handler();
//        handler.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                // 这里是延时后需要执行的代码
//                //退出导航组件
//                AmapNaviPage.getInstance().exitRouteActivity();
//            }
//        }, 5000);
    }

    @Override
    public void onLocationChange(AMapNaviLocation aMapNaviLocation) {
        Log.e("onGetNavigationText","onLocationChange");
    }

    //isEmulaterNavi - true代表是模拟导航到达目的地,false代表实时导航到达目的地
    @Override
    public void onArriveDestination(boolean isEmulaterNavi) {
        Map<String,Object> result=new HashMap<>();
        result.put("result",extraParams);

        channel.invokeMethod(NaviConstant.ARRIVE_Destination,result);
        //退出导航组件
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 这里是延时后需要执行的代码
                //退出导航组件
                AmapNaviPage.getInstance().exitRouteActivity();
            }
        }, 5000);
    }

    @Override
    public void onStartNavi(int i) {
        Log.e("onGetNavigationText","onStartNavi "+String.valueOf(i));
    }

    @Override
    public void onCalculateRouteSuccess(int[] ints) {
        Log.e("onGetNavigationText","onCalculateRouteSuccess "+String.valueOf(ints));

    }

    @Override
    public void onCalculateRouteFailure(int i) {
        Log.e("onGetNavigationText","onCalculateRouteFailure "+String.valueOf(i));
    }

    @Override
    public void onStopSpeaking() {
        Log.e("onGetNavigationText","onStopSpeaking");
    }

    @Override
    public void onReCalculateRoute(int i) {
        Log.e("onGetNavigationText","onReCalculateRoute "+String.valueOf(i));

    }

    @Override
    public void onExitPage(int i) {
        Log.e("onGetNavigationText","onExitPage "+String.valueOf(i));
    }

    @Override
    public void onStrategyChanged(int i) {
        Log.e("onGetNavigationText","onStrategyChanged "+String.valueOf(i));

    }

    @Override
    public void onArrivedWayPoint(int i) {
        Log.e("onGetNavigationText","onArrivedWayPoint "+String.valueOf(i));

    }

    @Override
    public void onMapTypeChanged(int i) {
        Log.e("onGetNavigationText","onMapTypeChanged "+String.valueOf(i));

    }

    @Override
    public void onNaviDirectionChanged(int i) {
        Log.e("onGetNavigationText","onNaviDirectionChanged "+String.valueOf(i));

    }

    @Override
    public void onDayAndNightModeChanged(int i) {
        Log.e("onGetNavigationText","onDayAndNightModeChanged "+String.valueOf(i));

    }

    @Override
    public void onBroadcastModeChanged(int i) {
        Log.e("onGetNavigationText","onBroadcastModeChanged "+String.valueOf(i));

    }

    @Override
    public void onScaleAutoChanged(boolean b) {
        Log.e("onGetNavigationText","onScaleAutoChanged "+b);

    }

    @Override
    public View getCustomMiddleView() {
        return null;
    }

    @Override
    public View getCustomNaviView() {
        return null;
    }

    @Override
    public View getCustomNaviBottomView() {
        return null;
    }
}

android端的代码到这里就完了

下面是Flutter端的代码

在Flutter新建dart文件,起名amap_navi_plugin.dart
代码如下:

import 'dart:convert';

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

//司机到达目的地附近的回调
typedef OnArriveCallBack=void Function(dynamic params);
//高德导航插件
class AMapNaviPlugin {
  //开始导航
  static const START_NAVI="startNavi";
  //同意隐私政策
  static const AGREE_PRIVACY="agreePrivacy";
  //到达目的地给flutter回调
  static const ARRIVE_Destination="arriveDestination";
  //取消导航
  static const CANCEL_NAVI="cancelNavi";


  //初始化通信管道
  static const String CHANNEL = "com.kdcf.channel/aMapNavi";
  static const platform = MethodChannel(CHANNEL);

  //开始导航
  //参数目的地经度、纬度、地点名称
  static Future<void> startAmapNavi(double endLongitude,double endLatitude,String endPlaceName,String poiId,Map extraParams) async {
    //通知安卓返回,到手机桌面
    try {
      Map map=Map();
      map['endLongitude']=endLongitude;
      map['endLatitude']=endLatitude;
      map['endPlaceName']=endPlaceName;
      map['extraParams']=extraParams;
      map['endPoiId']=poiId;
      // map['endLongitude']=103.85741;
      // map['endLatitude']=36.05407;
      // map['endPoiId']='';
      final dynamic result = await platform.invokeMethod(START_NAVI,map);
      if (result==200) {
        debugPrint("导航成功");
      }
    } on PlatformException catch (e) {
      debugPrint("通信失败 AMapNaviPlugin startAmapNavi:失败 ${e.toString()}");
      print(e.toString());
    }catch(e){
      debugPrint("导航失败:${e.toString()}");
    }
  }

  static void agreePrivacy() async {

    //通知安卓返回,到手机桌面
    try {
      final int result=await platform.invokeMethod(AGREE_PRIVACY);
      if (result==200) {
        debugPrint("同意导航隐私政策成功");
      }
    } on PlatformException catch (e) {
      debugPrint("通信失败 AMapNaviPlugin agreePrivacy:失败 ${e.toString()}");
      print(e.toString());
    }catch(e){
      debugPrint("同意导航隐私政策失败:${e.toString()}");
    }
  }

  //原生往flutter发消息,导航快到目的地的时候
  static void arriveDestination(OnArriveCallBack onArriveCallBack) async {
    //通知安卓返回,到手机桌面
    try {
       Future<dynamic> handler(MethodCall call) async {
        debugPrint("flutter收到消息:arriveDestination");
        switch (call.method) {
          case ARRIVE_Destination:
            Map result=call.arguments;
            debugPrint("ARRIVE_Destination参数:"+jsonEncode(result));
            onArriveCallBack(result);
            break;
        }
      }

      platform.setMethodCallHandler((call) => handler(call));
    } on PlatformException catch (e) {
      debugPrint("通信失败 AMapNaviPlugin arriveDestination:失败 ${e.toString()}");
      print(e.toString());
    }catch(e){
      debugPrint("arriveDestination失败:${e.toString()}");
    }
  }

  //flutter往原生发消息,取消订单的时候 取消导航
  static void cancelNavi() async {

    //通知安卓返回,到手机桌面
    try {
      final int result=await platform.invokeMethod(CANCEL_NAVI);
      if (result==200) {
        debugPrint("取消导航成功");
      }
    } on PlatformException catch (e) {
      debugPrint("通信失败 AMapNaviPlugin cancelNavi:失败 ${e.toString()}");
      print(e.toString());
    }catch(e){
      debugPrint("取消导航失败:${e.toString()}");
    }
  }


}


最后,使用方法

AMapNaviPlugin.startAmapNavi(longitude,latitude,destinationTitle,poiId,extraParams);

longitude为终点经度,latitude为终点纬度,destinationTitle为目的地的汉字名称,比如北京XXXX。poiId可以不传,extraParams可以不传。

以后还会完成的相关文章如下:

目前本人已完成项目里面以下技术的实现,但是还没时间写博客,工作太忙了,以后会完善。。。待续。。。

1. Flutter集成高德导航SDK(IOS篇)(OC语法)
2. Flutter集成高德导航SDK并且自定义导航UI页面(Android篇)(JAVA语法)
3. Flutter集成高德导航SDK并且自定义导航UI页面(IOS篇)(OC语法)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1882579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

技术反诈指南丨央视报了!基于“AI换脸”的新型电信网络诈骗猖獗

目录 利用“AI换脸”技术的诈骗 技术上防范新型电信网络诈骗 内蒙古鄂尔多斯市居民李女士近日遭遇了一起新型电信网络诈骗案。诈骗团伙利用“AI换脸”技术&#xff0c;合成了与李女士老同学相似的视频通话&#xff0c;以此作为诈骗的关键手段&#xff0c;成功骗取李女士信任。 …

[数据质量]手动实现 阿里云DataWorks 的数据质量监控告警功能

目录 手动实现 DataWorks 的数据质量监控告警功能1. 简介:2. 数据表准备2.1 tmp_monitor_tbl_info (数据监控信息表)2.2 tmp_monitor_rule_info (数据质量监控规则表)2.3 tmp_monitor_tbl_info_log_di (数据监控信息记录表) 3. 程序开发3.1 数据检查程序3.2 告警信息推送程序3.…

Navcat Premium17破解安装及数据库连接教程

一、前言 Navicat Premium 是一套数据库开发工具&#xff0c;是一个可多重连接数据库的管理工具。Navicat Premium让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 数据库。目前17已经支持了很久都没有支持的Redis数据库了。…

大数据之Zookeeper部署

文章目录 集群规划环境准备集群部署参考资料 集群规划 确定使用Hadoop101、hadoop102和hadoop103三台服务器来构建Zookeeper集群。 hadoop101hadoop102hadoop103zookeeperzookeeperzookeeper 环境准备 安装zookeeper前需要确保下面的环境配置成功&#xff0c;具体可以参考大…

七一建党节|热烈庆祝中国共产党成立103周年!

时光荏苒&#xff0c;岁月如梭。 在这热情似火的夏日&#xff0c; 我们迎来了中国共产党成立103周年的重要时刻。 这是一个值得全体中华儿女共同铭记和庆祝的日子&#xff0c; 也是激励我们不断前进的重要时刻。 103年&#xff0c; 风雨兼程&#xff0c;砥砺前行。 从嘉兴…

五种肉苁蓉属植物叶绿体基因组-文献精读25

Structural mutations of small single copy (SSC) region in the plastid genomes of five Cistanche species and inter-species identification 五种肉苁蓉属植物叶绿体基因组中小单拷贝 (SSC) 区域的结构突变及物种间鉴定 摘要 背景 肉苁蓉属是列当科的重要属类&#xf…

小型气象站:便携、高效的气象监测新选择

在气象监测领域&#xff0c;一款小巧而功能全面的设备正逐渐受到广泛关注——那就是小型气象站。它不仅体积小巧、重量轻&#xff0c;而且采用了众多先进技术&#xff0c;使其在气象数据的采集、传输和分析中展现出强大的能力。 小型气象站之所以备受青睐&#xff0c;首先得益于…

error LNK2019: 无法解析的外部符号 _SDL_main,该符号在函数 _main_getcmdline 中被引用

VC MFC情况下出现此问题&#xff0c; 网上搜索了很多文章无法解决。 error LNK2019: 无法解析的外部符号 _SDL_main&#xff0c;该符号在函数 _main_utf8 中被引用_sdl2main.lib出现无法解析的外部符号-CSDN博客 字符集必须设置为&#xff1a;

交叉编译 tcpdump libpcap

文章目录 交叉编译 tcpdump & libpcap概述源码下载交叉编译 libpcap交叉编译 tcpdump 交叉编译 tcpdump & libpcap 概述 tcpdump 是一个强大的命令行包分析器&#xff0c;libpcap 是一个可移植的用于网络流量捕获的 C/C 库。tcpdump 依赖于 libpcap 库&#xff0c;同…

Jenkins接口自动化项目的工程创建

jenkins的下载安装 jenkins下载的官网地址 https://www.jenkins.io/download/ java环境变量的配置下载 jenkins是用java语言编写的所以要配置java环境 需要安装java的JDK 推荐安装JDK17(https://blog.csdn.net/wochunyang/article/details/138520209) JDK17的下载地址 ht…

红黑树模拟

1.红黑树概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但每个节点上增加了一个存储位表示结点的颜色&#xff0c;可以是RED或BLACK。通过任何一条根到叶子节点的途径上各个节点的着色方式的限制&#xff0c;红黑树确保没有一条路径会超过其他路径的二倍&#xff0c;因…

基于Cisco模拟器的组网实验

课程目的 综合运用所学的网络原理、网络规划和网络集成等知识理论&#xff0c;按照下图所示&#xff0c;完成网络的规划、集成与配置&#xff0c;并利用ACL实现对网络的管理。 实验内容 连接并配置路由器&#xff0c;配置路由协议&#xff08;RIP或OSPF&#xff09;&#xf…

[Microsoft Office]Word设置页码从第二页开始为1

目录 第一步&#xff1a;设置页码格式 第二步&#xff1a;设置“起始页码”为0 第三步&#xff1a;双击页码&#xff0c;出现“页脚”提示 第四步&#xff1a;选中“首页不同” 第一步&#xff1a;设置页码格式 第二步&#xff1a;设置“起始页码”为0 第三步&#xff1a;双…

现在电气真的比不过计算机吗 ?

电气工程和计算机科学在今天的科技和工业领域中各有其重要性和发展空间&#xff0c;并不存在简单的比较谁“比不过”谁的情况。我收集制作一份plc学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向&#xff0c;包括了编程教学&#xff…

【爱上C++】详解string类2:模拟实现、深浅拷贝

在上一篇文章中我们介绍了string类的基本使用&#xff0c;本篇文章我们将讲解string类一些常用的模拟实现&#xff0c;其中有很多细小的知识点值得我们深入学习。Let’s go&#xff01; 文章目录 类声明默认成员函数构造函数析构函数拷贝构造函数深浅拷贝问题传统写法现代写法…

哪个量化软件最好用?散户也可以很快上手!QMT!

一、QMT是什么 QMT&#xff08;Quantitative Multi-market Trading System&#xff09;是一款专为高净值客户、量化爱好者及专业量化投资者设计的量化交易软件。它集行情显示、策略研究、交易执行和风控管理于一体&#xff0c;为投资者提供全方位的量化交易解决方案 二、QMT量化…

SAP配置发布WebService接口并调用(超级详细)

文章目录 前言一、案例介绍/笔者需求二、WebService是什么&#xff1f; a.传输协议 b.数据协议 c.WSDL d.UDDI 三、WebService 和 WebApi 的区别以及优缺点 a.主要区别 b.优缺点 四、SAP如何发布一个webser…

Perforce网络研讨会预告 | HelixCore vs SVN vs ClearCase:嵌入式开发中的数据管理趋势及工具对比分析

现如今&#xff0c;开发嵌入式软件涉及的规模比以往任何时候都庞大。团队在全球范围内不断扩展&#xff0c;文件数量呈指数级增长&#xff0c;项目每年所涉及的数字资产和元数据也更多&#xff0c;并且越来越多的团队成员要在相同的复杂项目中并行工作。 面对如此庞大的开发规…

《梦醒蝶飞:释放Excel函数与公式的力量》7.4 MID函数

第七章&#xff1a;文本处理函数 第4节&#xff1a;7.4 MID函数 7.4.1.MID函数简介 MID函数用于从文本字符串的指定位置开始提取指定数量的字符。它特别适用于从字符串中提取子字符串或处理具有特定格式的数据。 语法&#xff1a; MID(text, start_num, num_chars) - **t…

聚焦政企人才培养,打造多元化课程体系

树莓集团在课程内容上展现了显著的多元化特点&#xff0c;通过广泛的合作、创新的课程内容和产教融合的教学模式&#xff0c;为广大学子提供了全面、系统、专业的教育资源和实践机会。 1、专业广度&#xff1a;树莓集团旗下拥有树莓教育成都王老师摄影培训学校&#xff0c;作为…