TIME:2020年7月6日
再开始干货之前呢,我想先谈一谈自己对与高德地图API开发的一些心得体会。
首先,我们在确定了现目要使用高德API后,我们要从哪里入手开发呢?
1、首先要去官网上查阅文档,这一点很重要,你想要实现的功能官网的document中都会有介绍,但是呢,他只是简单的为你介绍一些回调函数,帮你梳理开发一个功能的需要用到的方法以及各种方法之间的调用关系,没有具体的开发过程,例如:某个函数具体是怎么编写的。这个时候就需要进入下一个阶段了
2、这个阶段就需要你建立之间的程序了,那么在开始编程之前呢,必要的包,环境配置肯定少不了了,做完这个之后就要进入第三阶段了。
3、下载源码,调试源码,让他能在自己的电脑上跑起来。这一点很重要,这样你就会对你要实现的功能在官方demo中有一个大致定位了,当然了,demo中的注释也有,但是肯定不如直接运行程序直观。然后进入第四步。
4、这时候需要你对官方demo示例进行剖析了,但是这也有很大的问题,官方demo将很多很多个功能集成在一个demo中,初学者又看不懂代码,这照葫芦画瓢也不知从何画起。这时候我的建议就是先找的要实现你主要功能的class,然后将该class直接copy到你的项目中,这时候你会发现,红色的错误要闪瞎你的狗眼了,不过不要慌,重点关注import出错部分,因为这是你在实现功能的时候需要使用到的class,没有是不行滴,然后再官方demo中找到copy。在此同时你就把需要的layout、value等等的都添加进去了。当你将全部报错解决了之后,那么你需要实现的功能的官方demo实现就提取出来了,这样是不是比你在整个demo中大海捞针要简单一点了。然后就可以运行代码了
4、但是运行的时候总是有错误来捣蛋,不用问,问就是度娘。当你运行起来的时候就可以进入下一步了。
5、做完以上工作呢,你基本上将你需要的部分提取到自己的项目中了,剩下的就是读代码、改代码;读代码、改代码;读代码、改代码;我们下面慢慢谈。
PS:我希望看到这篇博客的帅气小哥哥,漂亮小姐姐们先画几分钟时间看一下引言,因为毕竟第三方API有很多,我问不可能全都了解,所以以后开发的过程中肯定会碰到我们没用过的,所以掌握一种思路是非常重要的,这样的话就会触类旁通,举一反三了
当然,其实本编也是小白,只是做完高德地图API实现有感而发,不喜勿喷,下面正式干货来了。
本次要说的例子是实时定位+轨迹可视化,我们先来看看效果
跟着我的节奏要开始了
此处不做介绍,参见Android Studio工程配置
特别说明,我们要使用到的jar包有:
因为没实现搜索功能,所以不需要search,若要实现,需要加入search包
显示地图的基本思路:
详见:显示地图
1、再layout中放置一个com.amap.api.maps.MapView容器用来显示地图
2、获取并实例化MapView对象,MapView.getMap()方法获取地图
是不是so easy!!!
Layout:
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MainActivity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_test);
mapView = (MapView) findViewById(R.id.map);
mapView.onCreate(savedInstanceState);//必须要写
if (aMap == null) {
aMap = mapView.getMap();
}
}
详见:静态定位
定位的基本思路:
1、设置显示定位按钮并显示
2、继承定位监听接口并设置监听
3、显示定位图层并触发定位
4、初始化定位并开始定位
5、在定位回调函数实现功能
Layout:
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MainActivity:
基本思路1、2、3实现代码:
mLocationClient.setApiKey("7357dabe1561dc6a7a3a191c5a4a4679");
//获取地图控件引用
mapView = (MapView) findViewById(R.id.map);
//在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),实现地图生命周期管理
mapView.onCreate(savedInstanceState);
if (aMap == null) {
aMap = mapView.getMap();
//设置显示定位按钮 并且可以点击
UiSettings settings = aMap.getUiSettings();
aMap.setLocationSource(this);//设置了定位的监听
// 是否显示定位按钮
settings.setMyLocationButtonEnabled(true);
aMap.setMyLocationEnabled(true);//显示定位层并且可以触发定位,默认是flase
}
//初始化并开始定位
location();
基本思路4实现代码:
//初始化并开始定位
//也可以直接放在activate()回调函数中,该函数用于激活定位
private void location() {
//初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
//设置定位回调监听
mLocationClient.setLocationListener(this);
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位模式为Hight_Accuracy高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//设置是否只定位一次,默认为false
mLocationOption.setOnceLocation(false);
//设置是否强制刷新WIFI,默认为强制刷新
mLocationOption.setWifiActiveScan(true);
//设置是否允许模拟位置,默认为false,不允许模拟位置
mLocationOption.setMockEnable(false);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
//启动定位
mLocationClient.startLocation();
}
基本思路5的实现代码:
//定位回调函数,该示例实现了获取定位的数据
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation != null) {
if (aMapLocation.getErrorCode() == 0) {
//定位成功回调信息,设置相关消息
aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见官方定位类型表
aMapLocation.getLatitude();//获取纬度
aMapLocation.getLongitude();//获取经度
aMapLocation.getAccuracy();//获取精度信息
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(aMapLocation.getTime());
df.format(date);//定位时间
aMapLocation.getAddress();//地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
aMapLocation.getCountry();//国家信息
aMapLocation.getProvince();//省信息
aMapLocation.getCity();//城市信息
aMapLocation.getDistrict();//城区信息
aMapLocation.getStreet();//街道信息
aMapLocation.getStreetNum();//街道门牌号信息
aMapLocation.getCityCode();//城市编码
aMapLocation.getAdCode();//地区编码
// 如果不设置标志位,此时再拖动地图时,它会不断将地图移动到当前的位置
if (isFirstLoc) {
//设置缩放级别
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
//将地图移动到定位点
aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
//点击定位按钮 能够将地图的中心移动到定位点
mListener.onLocationChanged(aMapLocation);
//添加图钉
// aMap.addMarker(getMarkerOptions(amapLocation));
//获取定位信息
StringBuffer buffer = new StringBuffer();
buffer.append(aMapLocation.getCountry() + ""
+ aMapLocation.getProvince() + ""
+ aMapLocation.getCity() + ""
+ aMapLocation.getProvince() + ""
+ aMapLocation.getDistrict() + ""
+ aMapLocation.getStreet() + ""
+ aMapLocation.getStreetNum());
Toast.makeText(getApplicationContext(), buffer.toString(), Toast.LENGTH_LONG).show();
isFirstLoc = false;
}
} else {
//显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
Log.e("AmapError", "location Error, ErrCode:"
+ aMapLocation.getErrorCode() + ", errInfo:"
+ aMapLocation.getErrorInfo());
Toast.makeText(getApplicationContext(), "定位失败", Toast.LENGTH_LONG).show();
}
}
}
运行效果:
PS:这是有地图加定位的,是我位置问题(下面有地图图层)
详见:动态定位
动态定位基本思路:
1、获取地图对象,显示地图
2、创建AMapLocationClientOption对象
3、设置显示定位按钮并显示
4、继承定位监听接口并设置监听
5、在activate()回调中激活定位并设置定位间隔
6、在onLocationChanged()实现定位回调函数
7、在onStop()停止定位
8、在onDestory()销毁AMapLocationClientOption对象
Layout:
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MainActivity:
基本思路1、2、3、4的实现:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_test);
mapView = (MapView) findViewById(R.id.map);
mapView.onCreate(savedInstanceState);//必须要写
if (aMap == null) {
aMap = mapView.getMap();
//自定义地图
setUpMap();
}
// 设置定位监听
aMap.setLocationSource(this);
// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
aMap.setMyLocationEnabled(true);
}
private void setUpMap() {
// 设置小蓝点的图标
myLocationStyle = new MyLocationStyle();
// myLocationStyle.myLocationIcon(BitmapDescriptorFactory
// .fromResource(R.drawable.navi_map_gps_locked));// 设置小蓝点的图标
// 设置圆形的边框颜色
myLocationStyle.strokeColor(Color.argb(50, 30, 150, 180));
// 设置圆形的填充颜色
myLocationStyle.radiusFillColor(Color.argb(50, 30,150, 180));
// 设置圆形的边框粗细
myLocationStyle.strokeWidth(1.0f);
// 定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
//设置定位蓝点的Style
aMap.setMyLocationStyle(myLocationStyle);
//实例化UiSettings类对象
mUiSettings = aMap.getUiSettings();
//添加比例尺
mUiSettings.setScaleControlsEnabled(true);
// 设置默认定位按钮是否显示
aMap.getUiSettings().setMyLocationButtonEnabled(true);
}
基本思路5的实现:
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;
if (mLocationClient == null) {
//初始化定位
mLocationClient = new AMapLocationClient(this);
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位回调监听
mLocationClient.setLocationListener(this);
//设置为高精度定位模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//设置定位参数
mLocationClient.setLocationOption(mLocationOption);
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
// 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
// 在定位结束后,在合适的生命周期调用onDestroy()方法
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
// new Thread(new Runnable() {
// @Override
// public void run() {
// mLocationClient.startLocation();//启动定位
// }
// }).start();
mLocationClient.startLocation();//启动定位
}
}
基本思路6的实现:
private int index = 0;
//声明定位回调监听器
public void onLocationChanged(AMapLocation amapLocation) {
if (aMapLocation != null) {
if (aMapLocation.getErrorCode() == 0) {
//定位成功回调信息,设置相关消息
aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见官方定位类型表
aMapLocation.getLatitude();//获取纬度
aMapLocation.getLongitude();//获取经度
aMapLocation.getAccuracy();//获取精度信息
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(aMapLocation.getTime());
df.format(date);//定位时间
aMapLocation.getAddress();//地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
aMapLocation.getCountry();//国家信息
aMapLocation.getProvince();//省信息
aMapLocation.getCity();//城市信息
aMapLocation.getDistrict();//城区信息
aMapLocation.getStreet();//街道信息
aMapLocation.getStreetNum();//街道门牌号信息
aMapLocation.getCityCode();//城市编码
aMapLocation.getAdCode();//地区编码
// 如果不设置标志位,此时再拖动地图时,它会不断将地图移动到当前的位置
if (isFirstLoc) {
//设置缩放级别
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
//将地图移动到定位点
aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
//点击定位按钮 能够将地图的中心移动到定位点
mListener.onLocationChanged(aMapLocation);
//添加图钉
// aMap.addMarker(getMarkerOptions(amapLocation));
//获取定位信息
StringBuffer buffer = new StringBuffer();
buffer.append(aMapLocation.getLatitude() + ""
+ aMapLocation.getLongitude());
Toast.makeText(getApplicationContext(), buffer.toString(), Toast.LENGTH_LONG).show();
isFirstLoc = false;
}
基本思路7、8的实现:
@Override
public void deactivate() {
mListener = null;
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
mLocationClient = null;
}
详见:轨迹可视化
其本质就是在图层上画线、画点等。
轨迹可视化基本思路:
1、获取地图对象,显示地图
2、创建AMapLocationClientOption对象
3、设置显示定位按钮并显示
4、继承定位监听接口并设置监听
5、在activate()回调中激活定位并设置定位间隔
6、在onLocationChanged()实现定位回调函数,该函数实现轨迹可视化
7、在onStop()停止定位
8、在onDestory()销毁AMapLocationClientOption对象
PS: 其实就是在实时定位的基础上增加了画线、画点;
Layout:
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MainActivity:
基本思路1、2、3、4的实现:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_test);
mapView = (MapView) findViewById(R.id.map);
mapView.onCreate(savedInstanceState);//必须要写
if (aMap == null) {
aMap = mapView.getMap();
//自定义地图
setUpMap();
}
// 设置定位监听
aMap.setLocationSource(this);
// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
aMap.setMyLocationEnabled(true);
}
private void setUpMap() {
// 设置小蓝点的图标
myLocationStyle = new MyLocationStyle();
// myLocationStyle.myLocationIcon(BitmapDescriptorFactory
// .fromResource(R.drawable.navi_map_gps_locked));// 设置小蓝点的图标
// 设置圆形的边框颜色
myLocationStyle.strokeColor(Color.argb(50, 30, 150, 180));
// 设置圆形的填充颜色
myLocationStyle.radiusFillColor(Color.argb(50, 30,150, 180));
// 设置圆形的边框粗细
myLocationStyle.strokeWidth(1.0f);
// 定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
//设置定位蓝点的Style
aMap.setMyLocationStyle(myLocationStyle);
//实例化UiSettings类对象
mUiSettings = aMap.getUiSettings();
//添加比例尺
mUiSettings.setScaleControlsEnabled(true);
// 设置默认定位按钮是否显示
aMap.getUiSettings().setMyLocationButtonEnabled(true);
}
基本思路5的实现:
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;
if (mLocationClient == null) {
//初始化定位
mLocationClient = new AMapLocationClient(this);
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位回调监听
mLocationClient.setLocationListener(this);
//设置为高精度定位模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//设置定位参数
mLocationClient.setLocationOption(mLocationOption);
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
// 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
// 在定位结束后,在合适的生命周期调用onDestroy()方法
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
// new Thread(new Runnable() {
// @Override
// public void run() {
// mLocationClient.startLocation();//启动定位
// }
// }).start();
mLocationClient.startLocation();//启动定位
}
}
基本思路6的实现:
private int index = 0;
//声明定位回调监听器
public void onLocationChanged(AMapLocation amapLocation) {
if (mListener != null && amapLocation != null) {
if (amapLocation.getErrorCode() == 0) {
mListener.onLocationChanged(amapLocation);// 显示系统小蓝点
if(isFirst) {
//构造经纬度对象,并通过amapLocation对象传入经纬度数据
mLocalLatlng = new LatLng(amapLocation.getLatitude(),amapLocation.getLongitude());
//图层交互的方法,用于缩放地图
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLocalLatlng, 16));
isFirst = false;
}
} else {
String errText = "定位失败," + amapLocation.getErrorCode()+ ": " + amapLocation.getErrorInfo();
Log.e("AmapErr",errText);
}
}
if (amapLocation != null) {
mListener.onLocationChanged(amapLocation); //显示系统小蓝点,不写这一句无法显示到当前位置
amapLocation.getLocationType(); //获取当前定位结果来源,如网络定位结果,详见定位类型表
amapLocation.getAccuracy(); //获取精度信息
amapLocation.getBearing(); //获取方向角信息
amapLocation.getSpeed(); //获取速度信息 单位:米/秒
amapLocation.getLocationType(); //查看是什么类型的点
Log.e(TAG, "获取经纬度集合" + amapLocation);//打Log记录点是否正确
Log.e(TAG, "获取点的类型" + amapLocation.getLocationType());
//一边定位一边连线
drawLines(amapLocation);
privLocation = amapLocation;
Log.e("DDDDDDDDD", String.valueOf(Distance(amapLocation)));
// Toast.makeText(map_test.this, "距离" + Distance(amapLocation), Toast.LENGTH_SHORT).show();
//将坐标点存于数组里
if (amapLocation.getLatitude() != 0 && amapLocation.getLongitude() != 0) {
latLngPoints.add(new LatLngPoint(index++, new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude())));
}
} else {
//定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
Log.e("AmapError", "location Error, ErrCode:"
+ amapLocation.getErrorCode() + ", errInfo:" + amapLocation.getErrorInfo());
}
}
public void drawLines(AMapLocation curLocation) {
if (null == privLocation) {
return;
}
if (curLocation.getLatitude() != 0.0 && curLocation.getLongitude() != 0.0
&& privLocation.getLongitude() != 0.0 && privLocation.getLatitude() != 0.0) {
PolylineOptions options = new PolylineOptions();
//上一个点的经纬度
options.add(new LatLng(privLocation.getLatitude(), privLocation.getLongitude()));
//当前的经纬度
options.add(new LatLng(curLocation.getLatitude(), curLocation.getLongitude()));
options.width(10).geodesic(true).color(Color.GREEN);
aMap.addPolyline(options);
}
}
private double Distance(AMapLocation curLocation) {
double distance;
distance = AMapUtils.calculateLineDistance(new LatLng(privLocation.getLatitude(),
privLocation.getLongitude()), new LatLng(curLocation.getLatitude(),
curLocation.getLongitude()));
distance += distance;
return distance;
}
基本思路7、8的实现:
@Override
public void deactivate() {
mListener = null;
if (mLocationClient != null) {
// mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
mLocationClient = null;
}
@Override
protected void onStop() {
super.onStop();
mLocationClient.stopLocation();//停止定位
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
if(null != mLocationClient){
mLocationClient.onDestroy();
}
}
实现效果:
至此,轨迹可视化的功能全部实现,每一个step都是一个都是一个递进的过程,都是基于上一个step来实现下一个step的功能。到这里,我还是想在谈一下我的心得;其实代码具体的实现不是很重要,即使你自己不会写也没有关系;最重要的就是实现的思路以及你可以看得懂别人的代码。在官方demo中你想要的功能它都已经给你实现好了,你需要做的就是识别你需要的然后copy到你的工程中,然后看懂代码,自己修改
小编也是新手,所以在代码实现的过程中有一些bug,但是因为是一个小课设,所以我没有深入研究;下面是发现的bug;
bug1:轨迹移动不平滑:参见点平滑移动
bug2:可显示实时轨迹移动,但定位经纬度不变,我也没有做过多的测试,也没有想解决方案
,如果哪位大佬看出哪里错了,欢迎评论区留言
下载地址