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

先上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可以不传。

最后,附上一个运行视频:

Flutter集成高德导航Android端插件

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Cloudflare 推出一款免费对抗 AI 机器人的可防止抓取数据工具

上市云服务提供商Cloudflare推出了一种新的免费工具&#xff0c;可防止机器人抓取其平台上托管的网站以获取数据以训练AI模型。 一些人工智能供应商&#xff0c;包括谷歌、OpenAI 和苹果&#xff0c;允许网站所有者通过修改他们网站的robots.txt来阻止他们用于数据抓取和模型训…

系统架构设计师教程(清华第2版)<第1章 绪论>解读

系统架构设计师教程 第一章 绪论 1.1 系统架构概述1.1.1 系统架构的定义及发展历程1.1.2 软件架构的常用分类及建模方法1.1.3 软件架构的应用场景1.1.4 软件架构的发展未来1.2 系统架构设计师概述1.2.1 架构设计师的定义、职责和任务1.2.2 架构设计师应具备的专业素质1.3 如何成…

Unity中TimeLine的一些用法

Unity中TimeLine的一些用法 概念其他 概念 无Track模式&#xff08;PlayableAsset、PlayableBehaviour&#xff09; 1. 两者关系 运行在PlayableTrack中作用 PlayableBehaviour 实际执行的脚本字段并不会显示在timeline面板上 PlayableAsset PlayableBehaviour的包装器&#x…

电脑彻底删除的文件还能恢复吗怎么弄 电脑删除的文件怎么恢复 回收站也删了

实测可行的文件恢复方法&#xff0c;无论是彻底删除的文件&#xff0c;还是被清空的回收站文件&#xff0c;使用该方法都可以轻松找回。整个恢复过程操作简单&#xff0c;并且绝不会损伤电脑硬件。这意味着&#xff0c;您再也不用为误删文件而焦虑了。有关电脑彻底删除的文件还…

【Windows】Bootstrap Studio(网页设计)软件介绍及安装步骤

软件介绍 Bootstrap Studio 是一款专为前端开发者设计的强大工具&#xff0c;主要用于快速创建现代化的响应式网页和网站。以下是它的主要特点和功能&#xff1a; 直观的界面设计 Bootstrap Studio 提供了直观的用户界面&#xff0c;使用户能够轻松拖放元素来构建网页。界面…

audo dl上使用tensorrt llm,baichuan7B为例

1. 在社区镜像搜索 nvidia 找一个tensorrt llm 0.10 以上的版本&#xff0c;系统盘30g安装软件应该够用&#xff0c;免费的数据盘50G用来存放模型。baichuan7B原始模型应该会占用14G&#xff0c;转换为fp16的 ckpt后再占用14G&#xff0c;build后占用14G。总共需要占用42G&…

视频太大发不出去怎么处理,视频太大发不了邮件怎么办

在数字化时代&#xff0c;视频已成为我们分享生活、传递信息的重要方式。然而&#xff0c;当遇到视频文件过大&#xff0c;无法发送或分享时&#xff0c;你是否感到困扰&#xff1f;别担心&#xff0c;本文将为你揭秘轻松解决视频太大发不了的问题。 电脑频编辑器可以用于简单的…

工业智能网关的作用有哪些?工业智能网关与传统网关的主要区别-天拓四方

工业智能网关是一种专为工业环境设计的网络设备&#xff0c;具备数据采集、传输、协议转换以及边缘计算等功能。它作为连接工业设备与互联网的关键枢纽&#xff0c;不仅实现了工业设备的互联互通&#xff0c;还通过对采集到的数据进行实时分析&#xff0c;为工业生产的智能化管…

第一百四十三节 Java数据类型教程 - Java Boolean包装类

Java数据类型教程 - Java Boolean包装类 布尔类的对象包装一个布尔值。 Boolean.TRUE和Boolean.FALSE是布尔类型的两个常量&#xff0c;用于表示布尔值true和false值。 我们可以使用构造函数或valueOf()工厂方法创建一个布尔对象。 当解析字符串时&#xff0c;此类将处理“t…

软考-软件设计师 知识点整理(一篇就过了 建议收藏)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文☀️☀️☀️1.进制转换2.码制3.浮点数表示4.逻辑运算5.奇偶校验6.CRC循环冗余7.海明校验码8.CPU组成&am…

mybatis实现动态sql

第一章、动态SQL MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验&#xff0c;你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格&#xff0c;还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特…

关于虚拟机CentOS 7使用ssh无法连接(详细)

虚拟机CentOS 7使用ssh无法连接 猜测&#xff1a;可能是虚拟机软件的网关和和centos7的网关不同导致的问题。 首先打开CentOS7的终端, 输入ifconfig&#xff0c;查看一下系统的ip 打开虚拟机的虚拟网络编辑器, 查看一下网关, 发现确实不一样. 这里有两种方式, 要么修改虚…

104.二叉树的最大深度——二叉树专题复习

深度优先搜索&#xff08;DFS&#xff09;是一种常用的递归算法&#xff0c;用于解决树形结构的问题。在计算二叉树的最大深度时&#xff0c;DFS方法会从根节点开始&#xff0c;递归地计算左右子树的最大深度&#xff0c;然后在返回时更新当前节点所在路径的最大深度。 如果我…

gin项目部署到服务器并后台启动

文章目录 一、安装go语言环境的方式1.下载go安装包&#xff0c;解压&#xff0c;配置环境变量2.压缩项目上传到服务器并解压3.来到项目的根目录3.开放端口&#xff0c;运行项目 二、打包的方式1.在项目的根目录下输入以下命令2.把打包好的文件上传到服务器3.部署网站4.ssl证书 …

Web前端开发——HTML快速入门

HTML&#xff1a;控制网页的结构CSS&#xff1a;控制网页的表现 一、什么是HTML、CSS &#xff08;1&#xff09;HTML &#xff08;HyperText Markup Languaqe&#xff1a;超文本标记语言&#xff09; 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大。除了…

vienna整流器过零畸变原因分析

Vienna整流器是一种常见的三电平功率因数校正&#xff08;PFC&#xff09;整流器&#xff0c;广泛应用于电源和电能质量控制领域。由于其高效率、高功率密度和低谐波失真的特点&#xff0c;Vienna整流器在工业和电力电子应用中具有重要地位。然而&#xff0c;在实际应用中&…

新手拍短视频的些许建议

1、尽早行动&#xff0c;拒绝完美主义&#xff0c;有手机就能上车&#xff0c;一开始别花太多时间在打磨细节上。总是要准备好了后再做&#xff0c;就总比别人慢一步&#xff0c;可能永远也追不上了&#xff1b; 2、坚持发&#xff0c;度过难熬的启动期就行&#xff0c;不要走…

比Proxmox VE更易用的免费虚拟化平台

之前虚拟化一直玩Proxmox VE&#xff0c;最近发现一个更易用的虚拟化软件CSYun&#xff0c;他与Proxmox VE类似&#xff0c;都是一个服务器虚拟化平台。它不像VMware ESXi那么复杂&#xff0c;对于个人使用者和中小企业是一个比较好的选择。 这个软件所在的网址为&#xff1a;…

安装 VisualSVN Server提示HTTP服务无法启动的问题解决

安装 VisualSVN Server 版本&#xff1a;VisualSVN-Server-5.4.0-x64 安装包在安装到一半的时候&#xff0c;弹窗提示&#xff1a;HTTP服务无法启动&#xff0c;网上找了一大堆&#xff0c;说是service里面更改用户为本地用户什么的都没用用&#xff0c;点右键也无法启动。 …

基于Java的壁纸网站设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…