一、申请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, ), ), ); } }