打入高德内部获取到的 — Flutter 高德定位的使用方案

简介: 定位是我们开发中常用的功能,为了帮助大家理解,我从"高德总部"搞出来了这一份方案~

前言:兄弟们,咱们这个基础部分是已经结束了,学会之前的那些骚操作就基本上可以自己写点小东西玩玩了,现在来讲讲一些开发中常用的功能。

<img src=" title="img">

定位是我们开发中常用的功能,为了帮助大家理解,我冒着生命危险从高德总部偷出来了这一份方案!!

(求大家给个三联,我好跑路啊)img

话不多说,先上效果图:

在这里插入图片描述

准备阶段:

1.插件准备:

amap_flutter_location: ^2.0.0 #高德地图

插件地址

permission_handler: ^8.1.4 #权限管理,获取定位权限用

插件地址

2.在高德的开发者平台申请key:

第一步:注册开发者账号

高德开发者地址在这里
请添加图片描述

第二步:创建新的应用,并申请key

请添加图片描述

第三步:

请添加图片描述

关于如何获取SHA1,以及处理高德定位使用中的报错下一篇文章会详细的讲解

第四步获取到key:

请添加图片描述

第五步:获取自己需要的SDk

请添加图片描述

这样准备步骤就完成了。

第一步:SDK与权限处理

SDK处理:

在app文件夹下创建libs文件夹,把下载的SDK放入

请添加图片描述
然后在build.gradle中配置SDK:

dependencies{
    //添加demo中引入高德地图SDK
    implementation fileTree(include: ['*.zip'], dir: 'libs')
    implementation('com.amap.api:location:5.2.0')
    //定位功能
    compile 'com.amap.api:location:latest.integration'
}

权限处理:

在这个文件下配置:
请添加图片描述

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--访问网络-->
<uses-permission android:name="android.permission.INTERNET" />
<!--粗略定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--精确定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!--用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--用于写入缓存数据到扩展存储卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

第二步:配置Key

仍在这个文件中:
请添加图片描述

在application下:

meta-data
    android:name="com.amap.api.v2.apikey"
    android:value="//你自己的Key" />
<service android:name="com.amap.api.location.APSService"/> //定位

现在所有的配置都完成了!

第三步:代码使用

代码可以之间使用,放置文末了,只需要把自己的key替换一下

我们来看看官网的一些api:

定位结果是以map的形式返回的,具体内容为

 /// `callbackTime`:回调时间,格式为"yyyy-MM-dd HH:mm:ss"
  ///
  /// `locationTime`:定位时间, 格式为"yyyy-MM-dd HH:mm:ss"
  ///
  /// `locationType`:  定位类型, 具体类型可以参考https://lbs.amap.com/api/android-location-sdk/guide/utilities/location-type
  ///
  /// `latitude`:纬度
  ///
  /// `longitude`:精度
  ///
  /// `accuracy`:精确度
  ///
  /// `altitude`:海拔, android上只有locationType==1时才会有值
  ///
  /// `bearing`: 角度,android上只有locationType==1时才会有值
  ///
  /// `speed`:速度, android上只有locationType==1时才会有值
  ///
  /// `country`: 国家,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `province`: 省,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `city`: 城市,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `district`: 城镇(区),android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `street`: 街道,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `streetNumber`: 门牌号,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `cityCode`: 城市编码,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `adCode`: 区域编码, android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `address`: 地址信息, android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `description`: 位置语义, android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  ///
  /// `errorCode`: 错误码,当定位失败时才会返回对应的错误码, 具体错误请参考:https://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode
  ///
  /// `errorInfo`: 错误信息, 当定位失败时才会返回
  

详细代码:记得替换自己的Key哦!

import 'dart:async';
import 'dart:io';
import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

String _locationText;
class AmapPage extends StatefulWidget {
  @override
  _AmapPageState createState() => new _AmapPageState();
}

class _AmapPageState extends State<AmapPage> {
  Map<String, Object> _locationResult;

  StreamSubscription<Map<String, Object>> _locationListener;

  AMapFlutterLocation _locationPlugin = new AMapFlutterLocation();

  @override
  void initState() {
    super.initState();
    // 这个api是我在网上找的,必须用自己的,我的代码里也是我自己去申请的,ios的可以先不申请,但是要写,我的ios的key是用下面的这个
    /// 动态申请定位权限
    requestPermission();
    AMapFlutterLocation.setApiKey(
        "自己的key", "自己的key");
    ///设置Android和iOS的apiKey<br>
    ///
    /// 定位Flutter插件提供了单独的设置ApiKey的接口,
    /// 使用接口的优先级高于通过Native配置ApiKey的优先级(通过Api接口配置后,通过Native配置文件设置的key将不生效),
    /// 使用时可根据实际情况决定使用哪种方式
    ///
    ///key的申请请参考高德开放平台官网说明<br>
    ///
    ///Android: https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key
    ///
    ///iOS: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key


    ///iOS 获取native精度类型
    if (Platform.isIOS) {
      requestAccuracyAuthorization();
    }

    ///注册定位结果监听
    _locationListener = _locationPlugin
        .onLocationChanged()
        .listen((Map<String, Object> result) {
      setState(() {
        _locationResult = result;
        print('定位结果${result}');
        _locationText = ' ' +
            _locationResult['province'] +
            _locationResult['city'] +
            _locationResult['district'] +
            _locationResult['street'];
      });
      print('详细信息${_locationText}');
    });
  }

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

    ///移除定位监听
    if (null != _locationListener) {
      _locationListener.cancel();
    }

    ///销毁定位
    if (null != _locationPlugin) {
      _locationPlugin.destroy();
    }
  }

  ///设置定位参数
  void _setLocationOption() {
    if (null != _locationPlugin) {
      AMapLocationOption locationOption = new AMapLocationOption();

      ///是否单次定位
      locationOption.onceLocation = false;

      ///是否需要返回逆地理信息
      locationOption.needAddress = true;

      ///逆地理信息的语言类型
      locationOption.geoLanguage = GeoLanguage.ZH;

      locationOption.desiredLocationAccuracyAuthorizationMode =
          AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;

      locationOption.fullAccuracyPurposeKey = "AMapLocationScene";

      ///设置Android端连续定位的定位间隔
      locationOption.locationInterval = 2000;

      ///设置Android端的定位模式<br>
      ///可选值:<br>
      ///<li>[AMapLocationMode.Battery_Saving]</li>
      ///<li>[AMapLocationMode.Device_Sensors]</li>
      ///<li>[AMapLocationMode.Hight_Accuracy]</li>
      locationOption.locationMode = AMapLocationMode.Hight_Accuracy;

      ///设置iOS端的定位最小更新距离<br>
      locationOption.distanceFilter = -1;

      ///设置iOS端期望的定位精度
      /// 可选值:<br>
      /// <li>[DesiredAccuracy.Best] 最高精度</li>
      /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
      /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
      /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
      /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
      locationOption.desiredAccuracy = DesiredAccuracy.Best;

      ///设置iOS端是否允许系统暂停定位
      locationOption.pausesLocationUpdatesAutomatically = false;

      ///将定位参数设置给定位插件
      _locationPlugin.setLocationOption(locationOption);
    }
  }

  ///开始定位
  void _startLocation() {
    if (null != _locationPlugin) {
      ///开始定位之前设置定位参数
      _setLocationOption();
      _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: new Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new Container(
            alignment: Alignment.centerRight,
            width: 100.0,
            child: new Text('$key :'),
          ),
          new Container(width: 5.0),
          new Flexible(child: new Text('$value', softWrap: true)),
        ],
      ),
    );
  }

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

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

    return new MaterialApp(
        home: new Scaffold(
          appBar: new AppBar(
            title: new Text('高德定位测试'),
          ),
          body: new Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: widgets,
          ),
        ));
  }

  ///获取iOS native的accuracyAuthorization类型
  void requestAccuracyAuthorization() async {
    AMapAccuracyAuthorization currentAccuracyAuthorization =
    await _locationPlugin.getSystemAccuracyAuthorization();
    if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
      print("精确定位类型");
    } else if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
      print("模糊定位类型");
    } else {
      print("未知定位类型");
    }
  }

  /// 动态申请定位权限
  void requestPermission() async {
    // 申请权限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      print("定位权限申请通过");
    } else {
      print("定位权限申请不通过");
    }
  }

  /// 申请定位权限
  /// 授予定位权限返回true, 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      //已经授权
      return true;
    } else {
      //未授权则发起一次申请
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }
}

欢迎留言纠正 ~ 不妨给个点赞哈哈

相关文章
|
3月前
|
开发框架 Dart 前端开发
Android 跨平台方案对比之Flutter 和 React Native
本文对比了 Flutter 和 React Native 这两个跨平台移动应用开发框架。Flutter 使用 Dart 语言,提供接近原生的性能和丰富的组件库;React Native 则基于 JavaScript,具备庞大的社区支持和灵活性。两者各有优势,选择时需考虑团队技能和项目需求。
409 8
|
4月前
|
Android开发 C++ 开发者
Android经典实战之跨平台开发方案:Kotlin Multiplatform vs Flutter
本文对比了Kotlin Multiplatform与Flutter两大跨平台开发框架,从技术特性、性能、开发效率、UI体验、可扩展性及适用场景等维度进行了详尽分析,帮助开发者根据项目需求和技术背景选择最优方案。
166 2
|
7月前
|
Linux 开发者 iOS开发
Flutter笔记:桌面端应用多窗口管理方案
Flutter笔记:桌面端应用多窗口管理方案
515 0
|
7月前
flutter中使用图标(含自制图标库方案)
flutter中使用图标(含自制图标库方案)
1766 0
|
7月前
|
API
Flutter状态管理终极方案GetX第一篇——路由
Flutter状态管理终极方案GetX第一篇——路由 GetX是Flutter中一个非常流行的状态管理库,它不仅提供了简单易用的状态管理功能,还可以帮助我们方便地管理路由。在这篇文章中,我们将介绍如何使用GetX来实现路由管理。
366 0
|
7月前
|
开发者
Flutter状态管理终极方案GetX第二篇——状态管理
Flutter状态管理终极方案GetX第二篇——状态管理 在Flutter应用程序中,状态管理是必不可少的。GetX提供了简单易用的状态管理方案,使得开发者可以更加轻松地管理应用程序状态。下面介绍GetX中的状态管理方案。
280 0
|
Dart 前端开发 JavaScript
掌握这个关键技术,让你的APP开发事半功倍!——Flutter与其他方案的区别
掌握这个关键技术,让你的APP开发事半功倍!——Flutter与其他方案的区别
86 0
|
Android开发 iOS开发
flutter外接纹理实现方案
Flutter外部纹理是一种可以在Flutter中显示Android或iOS原生视图的技术。它允许您在Flutter应用程序中嵌入其他平台的视图,并且这些视图会像普通Flutter小部件一样被处理。
flutter外接纹理实现方案
|
容器
flutter 溢出七种布局方案
flutter 溢出七种布局方案
368 0
flutter 溢出七种布局方案
|
移动开发 Dart 小程序
Flutter-屏幕适配方案
我相信每个移动端开发者都避不开这个问题,就是屏幕适配。
Flutter-屏幕适配方案