flutter 集成百度地图

1.去百度地图官网下载插件地址
http://lbsyun.baidu.com/index.php?title=flutter/loc/download

  1. 在工程根目录下新建一个 plugins,把下载好的 bdmap_location_flutter_plugin 拖入到这个文件夹里面。如图


    image.png

    3.打开工程里面的 pubspec.yaml 添加以下代码 然后点package get

  bdmap_location_flutter_plugin:
    path: plugins/bdmap_location_flutter_plugin
image.png

出现以下表示正常已经下载好包

/Users/xxx/flutter/bin/flutter --no-color packages get
Running "flutter pub get" in flutter_app_demo...                    1.5s
Process finished with exit code 0

4.这个时候我们一定要运行下工程 ,一定要运行下工程 在强调一遍,因为运行成功会执行pod install...会把百度地图的依赖给配置好。

Launching lib/main.dart on Faith6p in debug mode...
Automatically signing iOS for device deployment using specified development team in Xcode project: C6VZ64TH78
Running pod install...
Running Xcode build...
Xcode build done.                                           12.2s
Failed to build iOS app
Error output from Xcode build:
↳
    ** BUILD FAILED **
 #import "BMKLocationkit/BMKLocationComponent.h"

5.到这来会出错会提示import导入的这个文件没有找到。这个时候我们需要打开xcode 手动配置依赖系统库与百度图的BMKLocationComponent,右击选择打开如下图


image.png

这里一定要打开Runner.xcworkspace因为这个是iospod管理的工程

6.打开工程选中 pods,然后在选中 bdmap_location_flutter_plugin 添加系统库以及一个百度官方的BMKLocationkit
添加BMKLocationkit 我需要点 + 然后选中 Add other,然后在点击Add file,将解压后的 BMKLocationKit.framework 文件复制或拖拽到工程文件夹中,左侧目录选中工程名,在TARGETS->Build Phases->Link Binary With Libaries中点击“+”按钮,在弹出的窗口中点击“Add Other”按钮,选择工程目录下的 BMKLocationKit.framework文件添加到工程中。如果不知道看下面的图


image.png

需要引入的系统库文件包括如下:

CoreLocation.framework
SystemConfiguration.framework
Security.framework
libsqlite3.0.tbd(xcode7以前为 libsqlite3.0.dylib)
CoreTelephony.framework
libc++.tbd(因需适配iOS12,需要将libstdc++.6.0.9.tbd 更新为libc++.tbd)
AdSupport.framework

在 TARGETS->General->Linked Frameworks and Libraries 中点击“+”,依次查找上述文件,添加到工程中,完成系统库文件的引入操作。

image.png

注意: 静态库中采用Objective-C++实现,因此需要您保证您工程中至少有一个.mm后缀的源文件(您可以将任意一个.m后缀的文件改名为.mm),或者在工程属性中指定编译方式,即在Xcode的Project -> Edit Active Target -> Build Setting 中找到 Compile Sources As,并将其设置为"Objective-C++"。 不报错可以不用管

7 ios申请权限


image.png

(1)在项目的 Info.plist 添加定位权限申请,根据您的实际业务需求,选择如下方式设置:
    - NSLocationWhenInUseUsageDescription:表示应用在前台的时候可以搜到更新的位置信息;
    - NSLocationAlwaysUsageDescription:表示应用在前台和后台(suspend 或 terminated)都可以获取到更新的位置数据;
    - NSLocationAlwaysAndWhenInUseUsageDescription:申请永久定位权限,以便应用在前台和后台都可以获取位置数据;

    (b)如果您需要永久定位的话,请设置如下:
        - 在Info.plist里配置NSLocationWhenInUseUsageDescription,NSLocationAlwaysUsageDescription,NSLocationAlwaysAndWhenInUseUsageDescription三项; 

官方文档 地址 https://lbsyun.baidu.com/index.php?title=ios-locsdk/guide/create-project/manual-create
到这里就已经完成了配置,接下来我们运行一下,然后点开始定位程序闪退,以下错误是,百度地图里面调用了__NSDictionaryM 的setObject 的值为null。如果正常可以忽略,《已经给百度地图递交过工单了》

2020-04-07 16:26:47.610285+0800 Runner[84851:1075309] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: poiList)'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23c7127e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff513fbb20 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23d03ab1 _CFThrowFormattedException + 194
    3   CoreFoundation                      0x00007fff23d0e6a6 -[__NSDictionaryM setObject:forKey:].cold.2 + 38
    4   CoreFoundation                      0x00007fff23cd1d4f -[__NSDictionaryM setObject:forKey:] + 1071
    5   bdmap_location_flutter_plugin       0x000000010f3b945b -[LocationFlutterPlugin BMKLocationManager:didUpdateLocation:orError:] + 6331
    6   bdmap_location_flutter_plugin       0x000000010f3c6f58 __52-[BMKLocationManager returnLastSemanticOnMainThread]_block_invoke + 950
    7   libdispatch.dylib                   0x000000010ffc5dd4 _dispatch_call_block_and_release + 12
    8   libdispatch.dylib                   0x000000010ffc6d48 _dispatch_client_callout + 8
    9   libdispatch.dylib                   0x000000010ffd4de6 _dispatch_main_queue_callback_4CF + 1500
    10  CoreFoundation                      0x00007fff23bd4049 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    11  CoreFoundation                      0x00007fff23bceca9 __CFRunLoopRun + 2329
    12  CoreFoundation                      0x00007fff23bce066 CFRunLoopRunSpecific + 438
    13  GraphicsServices                    0x00007fff384c0bb0 GSEventRunModal + 65
    14  UIKitCore                           0x00007fff48092d4d UIApplicationMain + 1621
    15  Runner                              0x000000010cdcbbbb main + 75
    16  libdyld.dylib                       0x00007fff5227ec25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

崩溃原因,是__NSDictionaryM调用方法setObject,设置了一个值为null,在ios里面是不允许的。这里我们通过ios的运行时方法交换处理了一下。在工程里添加三个文件即可,这里代码写好了拖入ios 工程即可
下载地址 链接: https://pan.baidu.com/s/1gOutSNT5zNOtd4A8J4YSMA 提取码: a7u8
把下载好的文件解压一下拖入ios工程中即可

image.png

8.然后我们去百度地图申请 ios key ,跟安卓key。地址 http://lbsyun.baidu.com/apiconsole/center#/home ,选控制台创建应用就好了,
image.png

9,按照官方提供的demo我们这里直接把代码复制到自己的工程里,先做下测试
大功告成
image.png

<如果你是跟我一样使用ios模拟器测试的话,想要自定义经纬度的可按一下步骤,选择模拟器点击菜单debug-Location-Costom Locarion>
image.png

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

import 'package:bdmap_location_flutter_plugin/bdmap_location_flutter_plugin.dart';
import 'package:bdmap_location_flutter_plugin/flutter_baidu_location.dart';
import 'package:bdmap_location_flutter_plugin/flutter_baidu_location_android_option.dart';
import 'package:bdmap_location_flutter_plugin/flutter_baidu_location_ios_option.dart';
class MapLocation extends StatefulWidget {
  @override
  _MapLocationState createState() => _MapLocationState();
}

class _MapLocationState extends State<MapLocation> {
  Map<String, Object> _loationResult;
  BaiduLocation _baiduLocation; // 定位结果

  StreamSubscription<Map<String, Object>> _locationListener;

  LocationFlutterPlugin _locationPlugin = new LocationFlutterPlugin();

  @override
  void initState() {
    super.initState();

    /// 动态申请定位权限
    _locationPlugin.requestPermission();

    /// 设置ios端ak, android端ak可以直接在清单文件中配置
    LocationFlutterPlugin.setApiKey("iOS申请的key换成自己的");

    _locationListener = _locationPlugin
        .onResultCallback()
        .listen((Map<String, Object> result) {
      setState(() {
        _loationResult = result;
        try {
          _baiduLocation = BaiduLocation.fromMap(result); // 将原生端返回的定位结果信息存储在定位结果类中
//          print(_baiduLocation);
        } catch (e) {
          print(e);
        }
      });
    });

  }

  @override
  void dispose() {
    super.dispose();
    if (null != _locationListener) {
      _locationListener.cancel(); // 停止定位
    }
  }

  /// 设置android端和ios端定位参数
  void _setLocOption() {
    /// android 端设置定位参数
    BaiduLocationAndroidOption androidOption = new BaiduLocationAndroidOption();
    androidOption.setCoorType("bd09ll"); // 设置返回的位置坐标系类型
    androidOption.setIsNeedAltitude(true); // 设置是否需要返回海拔高度信息
    androidOption.setIsNeedAddres(true); // 设置是否需要返回地址信息
    androidOption.setIsNeedLocationPoiList(true); // 设置是否需要返回周边poi信息
    androidOption.setIsNeedNewVersionRgc(true); // 设置是否需要返回最新版本rgc信息
    androidOption.setIsNeedLocationDescribe(true); // 设置是否需要返回位置描述
    androidOption.setOpenGps(true); // 设置是否需要使用gps
    androidOption.setLocationMode(LocationMode.Hight_Accuracy); // 设置定位模式
    androidOption.setScanspan(1000); // 设置发起定位请求时间间隔

    Map androidMap = androidOption.getMap();

    /// ios 端设置定位参数
    BaiduLocationIOSOption iosOption = new BaiduLocationIOSOption();
    iosOption.setIsNeedNewVersionRgc(true); // 设置是否需要返回最新版本rgc信息
    iosOption.setBMKLocationCoordinateType("BMKLocationCoordinateTypeBMK09LL"); // 设置返回的位置坐标系类型
    iosOption.setActivityType("CLActivityTypeAutomotiveNavigation"); // 设置应用位置类型
    iosOption.setLocationTimeout(10); // 设置位置获取超时时间
    iosOption.setDesiredAccuracy("kCLLocationAccuracyBest");  // 设置预期精度参数
    iosOption.setReGeocodeTimeout(10); // 设置获取地址信息超时时间
    iosOption.setDistanceFilter(100); // 设置定位最小更新距离
    iosOption.setAllowsBackgroundLocationUpdates(true); // 是否允许后台定位
    iosOption.setPauseLocUpdateAutomatically(true); //  定位是否会被系统自动暂停

    Map iosMap = iosOption.getMap();

    _locationPlugin.prepareLoc(androidMap, iosMap);
  }

  /// 启动定位
  void _startLocation() {
    if (null != _locationPlugin) {
      _setLocOption();
      _locationPlugin.startLocation();
    }
  }

  /// 停止定位
  void _stopLocation() {
    if (null != _locationPlugin) {
      _locationPlugin.stopLocation();
    }
  }

  Container _createButtonContainer() {
    return new Container(
        alignment: Alignment.center,
        child: new Row(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            new RaisedButton(
              onPressed: _startLocation,
              child: new Text('开始定位'),
              color: Colors.blue,
              textColor: Colors.white,
            ),
            new Container(width: 20.0),
            new RaisedButton(
              onPressed: _stopLocation,
              child: new Text('停止定位'),
              color: Colors.blue,
              textColor: Colors.white,
            )
          ],
        ));
  }

  Widget _resultWidget(key, value) {
    return new Container(
      child: Center(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new Text('$key:' ' $value'),
            ]
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> widgets = new List();

    if (_loationResult != null) {
      _loationResult.forEach((key, value) {
        widgets.add(_resultWidget(key, value));
      });
    }

    widgets.add(_createButtonContainer());


    return new MaterialApp(
        home: new Scaffold(
          appBar: new AppBar(
            title: new Text('基础定位'),
          ),
          body: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: widgets,
          ),
        ));
  }
}

写在在最后

自己在集成的是也遇到了很多问题,我都在上面列出来希望可以帮到你。
更新一个问题,有个小伙伴用flutter创建的ios oc项目,集成一直报错误,建议换成ios swfit的
2020年06月05日17:15:04 解决oc项目报错
因为你创建的是oc 工程百度插件是用swift写的,需要一个文件来桥接
在工程里,新建一个swift文件就好了,名字随便起 xcode 会自动帮你桥接,

2020年08月04日10:58:20 有跟多小伙伴按照流程集成到后面还是提示 #import "BMKLocationkit/BMKLocationComponent.h"没有找到,需要把BMKLocationKit.framework的库放到iOS目录下的Pods文件夹里面,然后在从新add引入 。

推荐阅读更多精彩内容