一、申请APIkey

前往 https://lbs.amap.com/api/android-sdk/guide/create-project/get-key 申请APIkey,新建一个应用,分别添加key,其中要获取SHA1值。

  • Mac下AndroidStudio获取SHA1值:
    第一步、打开Android Studio的Terminal工具;
    第一步、输入命令:cd ~/.android ;
    第二步、输入命令:keytool -list -v -keystore debug.keystore ;
    第四步、输入Keystore密码,一般直接回车就行,或者输入android。

这里就获取到SHA1值,就可以在高德地图后台申请APIkey了。

而packageName就在build.gradle(app)里,取applicationId。

二、配置集成高德地图

依賴

amap_base: ^0.3.5

Android配置,在build.gradle(app)中添加AMAP_KEY即可。

android {
    .... 你的代码
    defaultConfig {
        .....
        manifestPlaceholders = [
                AMAP_KEY : "aa9f0cf8574400f2af0078392c556e25", /// 高德地图key
        ]
     multiDexEnabled true
}
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    //高德
    implementation "com.amap.api:location:latest.integration"
}

添加 implementation "com.amap.api:location:latest.integration"

在 application 添加

<meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="你的key"/>

在application外

<uses-permission android:name="android.permission.INTERNET" />
    <!--用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <!--用于访问GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <!--这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <!--用于访问网络,网络定位需要上网-->
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <!--用于申请调用A-GPS模块-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>

main添加AMap.init('1a83798190514cf82dbe799d6d4ac71c');

void main() async{
  AMap.init('1a83798190514cf82dbe799d6d4ac71c');
  var userState = UserState();
  var providers = Providers();
  var counter = Counter();
  providers
    //多個狀態的管理
    ..provide(Provider<Counter>.value(counter))
    ..provide(Provider<UserState>.value(userState));
  //runApp(MyApp());
  runApp(
    ProviderNode(
      child: MyApp(),
      providers: providers,
    ),
  );
}

主要代碼

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


class GouldMap extends StatefulWidget {
  @override
  _GouldMapState createState() => _GouldMapState();
}

class _GouldMapState extends State<GouldMap> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('高德地圖'),
      ),
      body: Container(
        child: MapPage(),
      ),
    );
  }
}

class MapPage extends StatefulWidget {
  MapPage();

  factory MapPage.forDesignTime() => MapPage();

  @override
  _ShowMapScreenState createState() => _ShowMapScreenState();
}

class _ShowMapScreenState extends State<MapPage> {
  AMapController _controller;
  MyLocationStyle _myLocationStyle = MyLocationStyle();
  StreamSubscription _subscription;

  //region 界面布局
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        elevation: 0,
        centerTitle: true,
        title: Text(
          '显示地图',
          style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
        ),
      ),
      body: Column(
        children: <Widget>[
          Flexible(
            child: AMapView(
              onAMapViewCreated: (controller) {
                _controller = controller;
                _subscription = _controller.markerClickedEvent
                    .listen((it) => print('地图点击: 坐标: $it'));
                //点击标注图标执行
                _controller.addMarker(MarkerOptions(
                  icon: 'images/place.png',
                  position: LatLng(22.2477900000, 113.5761300000),
                  title: '哈哈',
                  snippet: '呵呵',
                ));
              },
              amapOptions: AMapOptions(
                compassEnabled: false,
                zoomControlsEnabled: true,
                logoPosition: LOGO_POSITION_BOTTOM_CENTER,
                camera: CameraPosition(
                  target: LatLng(22.2477900000, 113.5761300000),
                  zoom: 15,
                ),
              ),
            ),
          ),
          Flexible(
            child: Builder(
              builder: (context) {
                return ListView(
                  children: <Widget>[
                    BooleanSetting(
                      head: '显示自己的位置 [Android, iOS]',
                      selected: false,
                      onSelected: (value) {
                        _updateMyLocationStyle(context, showMyLocation: value);
                      },
                    ),
                    RaisedButton(
                        child: Text('步行导航'),
                        onPressed: () {
                          AMapNavi().startNavi(
                            lat: 22.2477900000,
                            lon: 113.5761300000,
                            naviType: AMapNavi.walk,
                          );
                        }),
                    RaisedButton(
                        child: Text('骑行导航'),
                        onPressed: () {
                          AMapNavi().startNavi(
                            lat: 22.2477900000,
                            lon: 113.5761300000,
                            naviType: AMapNavi.ride,
                          );
                        }),
                    RaisedButton(
                        child: Text('车载导航'),
                        onPressed: () {
                          AMapNavi().startNavi(
                            lat: 22.2477900000,
                            lon: 113.5761300000,
                            naviType: AMapNavi.drive,
                          );
                        })
                  ],
                );
              },
            ),
          ),
        ],
      ),
    );
  }
  //endregion

  //region 权限申请
  void _updateMyLocationStyle(
      BuildContext context, {
        String myLocationIcon,
        double anchorU,
        double anchorV,
        Color radiusFillColor,
        Color strokeColor,
        double strokeWidth,
        int myLocationType,
        int interval,
        bool showMyLocation,
        bool showsAccuracyRing,
        bool showsHeadingIndicator,
        Color locationDotBgColor,
        Color locationDotFillColor,
        bool enablePulseAnnimation,
        String image,
      }) async {
    if (await Permissions().requestPermission()) {
      _myLocationStyle = _myLocationStyle.copyWith(
        myLocationIcon: myLocationIcon,
        anchorU: anchorU,
        anchorV: anchorV,
        radiusFillColor: radiusFillColor,
        strokeColor: strokeColor,
        strokeWidth: strokeWidth,
        myLocationType: myLocationType,
        interval: interval,
        showMyLocation: showMyLocation,
        showsAccuracyRing: showsAccuracyRing,
        showsHeadingIndicator: showsHeadingIndicator,
        locationDotBgColor: locationDotBgColor,
        locationDotFillColor: locationDotFillColor,
        enablePulseAnnimation: enablePulseAnnimation,
      );
      _controller.setMyLocationStyle(_myLocationStyle);
    } else {
      //ToastUtils.showToast( '权限不足');
    }
  }
  //endregion

  //region 销毁事件
  @override
  void dispose() {
    _controller?.dispose();
    _subscription?.cancel();
    super.dispose();
  }
//endregion

}

const SPACE_NORMAL = const SizedBox(width: 8, height: 8);
const kDividerTiny = const Divider(height: 1);

/// 连续设置
class ContinuousSetting extends StatefulWidget {
  const ContinuousSetting({
    Key key,
    @required this.head,
    @required this.onChanged,
    this.min = 0,
    this.max = 1,
  }) : super(key: key);

  final String head;
  final ValueChanged<double> onChanged;
  final double min;
  final double max;

  @override
  _ContinuousSettingState createState() => new _ContinuousSettingState();
}

class _ContinuousSettingState extends State<ContinuousSetting> {
  double _value;

  @override
  void initState() {
    super.initState();
    _value = 0;
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(
        left: 16,
        top: 16,
        right: 16,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(widget.head, style: Theme.of(context).textTheme.subhead),
          SPACE_NORMAL,
          Slider(
            value: _value,
            min: widget.min,
            max: widget.max,
            onChanged: (_) {},
            onChangeEnd: (value) {
              setState(() {
                _value = value;
                widget.onChanged(value);
              });
            },
          ),
          kDividerTiny,
        ],
      ),
    );
  }
}

/// 离散设置
class DiscreteSetting extends StatelessWidget {
  const DiscreteSetting({
    Key key,
    @required this.head,
    @required this.options,
    @required this.onSelected,
  }) : super(key: key);

  final String head;
  final List<String> options;
  final ValueChanged<String> onSelected;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        PopupMenuButton<String>(
          onSelected: onSelected,
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Text(head, style: Theme.of(context).textTheme.subhead),
          ),
          itemBuilder: (context) {
            return options
                .map((value) => PopupMenuItem<String>(
              child: Text(value),
              value: value,
            ))
                .toList();
          },
        ),
        kDividerTiny,
      ],
    );
  }
}

/// 颜色设置
class ColorSetting extends StatelessWidget {
  const ColorSetting({
    Key key,
    @required this.head,
    @required this.onSelected,
  }) : super(key: key);

  final String head;
  final ValueChanged<Color> onSelected;

  @override
  Widget build(BuildContext context) {
    return DiscreteSetting(
      head: head,
      options: ['绿色', '红色', '黄色'],
      onSelected: (value) {
        Color color;
        switch (value) {
          case '绿色':
            color = Colors.green.withOpacity(0.6);
            break;
          case '红色':
            color = Colors.red.withOpacity(0.6);
            break;
          case '黄色':
            color = Colors.yellow.withOpacity(0.6);
            break;
        }

        onSelected(color);
      },
    );
  }
}

/// 二元设置
class BooleanSetting extends StatefulWidget {
  const BooleanSetting({
    Key key,
    @required this.head,
    @required this.onSelected,
    this.selected = false,
  }) : super(key: key);

  final String head;
  final ValueChanged<bool> onSelected;
  final bool selected;

  @override
  _BooleanSettingState createState() => _BooleanSettingState();
}

class _BooleanSettingState extends State<BooleanSetting> {

  bool _selected;

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

    _selected = widget.selected;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SwitchListTile(
          title: Text(widget.head),
          value: _selected,
          onChanged: (selected) {
            setState(() {
              _selected = selected;
              widget.onSelected(selected);
            });
          },
        ),
        kDividerTiny,
      ],
    );
  }
}

/// 输入文字
class TextSetting extends StatelessWidget {
  final String leadingString;
  final String hintString;

  const TextSetting({
    Key key,
    @required this.leadingString,
    @required this.hintString,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Text(leadingString),
      title: TextFormField(
        decoration: InputDecoration(
          hintText: hintString,
        ),
      ),
    );
  }
}
View Code
12-20 19:16