集成地图前,进行了一个小的调研。感觉百度在地图开发上应该是和google这种级别的,所以首先选择了百度sdk进行集成。花了一天的功夫,大概实现了需求。快下班的时候还有些时间,就顺便看了下高德,从新建project到demo实现出来,只用了半小时左右。真是没有对比就没有伤害。可能是功能上大同小异,但是我想说的是:无论是开发文档,还是测试Demo。都不是一个级别的产品。尤其让我意外的是高德的Demo连warn都很少,可以说基本没有。真是教科书般的文档与Demo。想到了集成其他SDK时候的痛苦,都没有集成高德SDK这样的顺畅。顺便看了下腾讯地图,从文档上来说:高德,腾讯,百度。技术上不做过多评价大同小异,都能实现。
第一次集成建议:直接看文档
http://lbs.amap.com/api/android-sdk/guide/create-project/android-studio-create-project#gradle_sdk
文档上获取sha1的方式有点麻烦,可以在Android studio 中更简单的获取
一定注意自己配置的debug.keystore,文件是不是正确的。
gardle添加
//这里说明一下根据需求添加,高德分为4个部分,定位,地图,搜索,导航。这四个部分都有相应的so和jar。地图还分为(3D、2D)。我们项目需要下面的两个,所以就写了这俩。
//3D地图so及jar
compile 'com.amap.api:3dmap:latest.integration'
//搜索功能
compile 'com.amap.api:search:latest.integration'
清单文件配置
请求权限配置
略(自己根据官网和项目进行增删)
高德key
布局文件引用
这里有两种主要的实现方式
这六个组件实现的功能都是一样的
区别主要是:TextureView解决了,黑边问题,如果你的容器是fragment,建议你用TextureView如果是Activity则无所谓。
每个里面包含的三个组件的区别是:第一个生命周期需要自己管理,后面两种都是fragment生命周期帮你管理了。Support区别是支持更早的版本。
GLSurfaceView:
MapView、MapFragment、SupportMapFragment
TextureView:
TextureMapView、TextureMapFragment、TextureSupportMapFragment
代码实现
下面是部分常用方法,具体需求具体实现
/**
* 获取 AMap 对象
*/
private void setUpMapIfNeeded() {
if (aMap == null) {
aMap = ((TextureSupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
}
}
private void initMyLocation() {
MyLocationStyle myLocationStyle;
myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE) ;//定位一次,且将视角移动到地图中心点。
myLocationStyle.showMyLocation(true);//设置是否显示定位小蓝点,用于满足只想使用定位,不想使用定位小蓝点的场景,设置false以后图面上不再有定位蓝点的概念,但是会持续回调位置信息。
//myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示,非必需设置。
aMap.getUiSettings().setZoomControlsEnabled(false);
aMap.getUiSettings().setRotateGesturesEnabled(false);
aMap.getUiSettings().setTiltGesturesEnabled(false);
aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
aMap.moveCamera(CameraUpdateFactory.zoomTo(12));//地图显示级别
}
注意添加混淆
3D 地图 V5.0.0之前:
-keep class com.amap.api.maps.**{*;}
-keep class com.autonavi.amap.mapcore.*{*;}
-keep class com.amap.api.trace.**{*;}
3D 地图 V5.0.0之后:
-keep class com.amap.api.maps.**{*;}
-keep class com.autonavi.**{*;}
-keep class com.amap.api.trace.**{*;}
定位
-keep class com.amap.api.location.**{*;}
-keep class com.amap.api.fence.**{*;}
-keep class com.autonavi.aps.amapapi.model.**{*;}
搜索
-keep class com.amap.api.services.**{*;}
2D地图
-keep class com.amap.api.maps2d.**{*;}
-keep class com.amap.api.mapcore2d.**{*;}
导航
-keep class com.amap.api.navi.**{*;}
-keep class com.autonavi.**{*;}
要求显示用户所在位置,位置上的marker是从网络加载的图像。
用户发布活动显示的marker,也是要求显示发布者头像。
建议用Glide获取到bitmap的时候在aMap.addMarker()
Glide.with(TopMapFragment.this)
.load(mMyList.get(i).getHead_image())
.asBitmap().into(new SimpleTarget() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation super Bitmap> glideAnimation) {
imageView.setImageBitmap(resource);
markerOption.icon(BitmapDescriptorFactory.fromView(imageView));
Marker marker = aMap.addMarker(markerOption);
}
});
方式一:直接解析布局(代码:略)用BitmapDescriptorFactory.fromView()显示
需求是实现一套自己的路线规划,不知道为啥不用地图自带的。
参照美团app路线规划功能实现
难点倒是没有,东西比较多,好多东西又是高德写好的,只需要参照Demo就行了。需要理解那些东西,才能更好的重新组装。
支持四种类型的查询bus、walk、drive、ride
下面的没有ride
mRouteSearch = new RouteSearch(this);
mRouteSearch.setRouteSearchListener(this);
第二步:实现查询
RouteSearch.BusRouteQuery query = new RouteSearch.BusRouteQuery(fromAndTo, RouteSearch.BUS_DEFAULT,
mCurrentCityName, 0);
RouteSearch.DriveRouteQuery query1 = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault, null,
null, "");
RouteSearch.WalkRouteQuery query2 = new RouteSearch.WalkRouteQuery(fromAndTo, RouteSearch.WALK_DEFAULT);
mRouteSearch.calculateBusRouteAsyn(query);
mRouteSearch.calculateDriveRouteAsyn(query1);
mRouteSearch.calculateWalkRouteAsyn(query2);
第三步:处理查询结果
@Override
public void onBusRouteSearched(BusRouteResult result, int errorCode) {
if (errorCode == AMapException.CODE_AMAP_SUCCESS) {
if (result != null && result.getPaths() != null) {
if (result.getPaths().size() > 0) {
mBusRouteResult = result;
mRouteBusFragment.setUpdateData(mBusRouteResult);
} else if (result != null && result.getPaths() == null) {
Log.e(TAG, "onBusRouteSearched: 出错");
}
} else {
}
} else {
}
}
@Override
public void onDriveRouteSearched(DriveRouteResult result, int errorCode) {
if (errorCode == AMapException.CODE_AMAP_SUCCESS) {
if (result != null && result.getPaths() != null) {
if (result.getPaths().size() > 0) {
mDriveRouteResult = result;
mRouteCarFragment.setRouteData(mDriveRouteResult);
} else if (result != null && result.getPaths() == null) {
}
} else {
}
} else {
}
}
@Override
public void onWalkRouteSearched(WalkRouteResult result, int errorCode) {
if (errorCode == AMapException.CODE_AMAP_SUCCESS) {
if (result != null && result.getPaths() != null) {
if (result.getPaths().size() > 0) {
mWalkRouteResult = result;
mRouteWalkFragment.setRouteData(mWalkRouteResult);
} else if (result != null && result.getPaths() == null) {
}
} else {
}
} else {
}
}
@Override
public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {
Log.e(TAG, "onRideRouteSearched: " + rideRouteResult);
}
这里公交地铁的实现官方给的demo代码有点问题,一些参数需要自己判断,比如stepList.get(i).getBusLines()。这个参数永远不会是null,
官方却判断它是否为空,它没有数据的时候也返回一个集合,只不过size为0。stepList.get(i).getRailway()确总是为null。无论有没有地铁。
不知道他们是把它当成火车还是地铁。
公交(地铁)路线
private void setBusMap() {
BusRouteOverlay busRouteOverlay = new BusRouteOverlay(
this, aMap, mBusPath,
mRouteResult.getStartPos(),
mRouteResult.getTargetPos());
busRouteOverlay.removeFromMap();
busRouteOverlay.addToMap();
busRouteOverlay.zoomToSpan();
aMap.moveCamera(CameraUpdateFactory.zoomTo(12));
List stepList = mBusPath.getSteps();
Boolean isFirst=true;
for (int i = 0; i < stepList.size(); i++) {
if (stepList.get(i).getWalk()!=null && stepList.get(i).getWalk().getDistance() > 0
&&stepList.get(i).getBusLines().size()>0
) {
if (isFirst){
isFirst=false;
mList.add("步行"+ stepList.get(i).getWalk().getDistance()+"米,到达起点。乘坐"
+stepList.get(i).getBusLines().get(0).getBusLineName()+"共"+
stepList.get(i).getBusLines().get(0).getPassStationNum()+"站" );
}else {
mList.add("步行"+ stepList.get(i).getWalk().getDistance()+"米。换乘"
+stepList.get(i).getBusLines().get(0).getBusLineName()+"共"+
stepList.get(i).getBusLines().get(0).getPassStationNum()+"站" );
}
}
if (stepList.get(i).getWalk()!=null&&stepList.get(i).getWalk().getDistance()>0
&&stepList.get(i).getBusLines().size()==0 &&stepList.get(i).getRailway()==null
){
mList.add(
"步行"+ stepList.get(i).getWalk().getDistance()+"米,到达目的地。");
}
}
mStepAdapter.notifyDataSetChanged();
}
步行结果
private void setWalkMap() {
WalkPath walkPath = (( WalkRouteResult)mRouteResult).getPaths()
.get(0);
WalkRouteOverlay walkRouteOverlay = new WalkRouteOverlay(
this, aMap, walkPath,
mRouteResult.getStartPos(),
mRouteResult.getTargetPos());
walkRouteOverlay.removeFromMap();
walkRouteOverlay.addToMap();
walkRouteOverlay.zoomToSpan();
aMap.moveCamera(CameraUpdateFactory.zoomTo(12));
for (int i = 0; i < walkPath.getSteps().size(); i++) {
mList.add( walkPath.getSteps().get(i).getInstruction());
}
mStepAdapter.notifyDataSetChanged();
}
开车结果
private void setCarMap() {
DrivePath drivePath = ((DriveRouteResult)mRouteResult).getPaths()
.get(0);
DrivingRouteOverlay drivingRouteOverlay = new DrivingRouteOverlay(
this, aMap, drivePath,
mRouteResult.getStartPos(),
mRouteResult.getTargetPos(), null);
drivingRouteOverlay.setNodeIconVisibility(true);//设置节点marker是否显示
drivingRouteOverlay.setIsColorfulline(true);//是否用颜色展示交通拥堵情况,默认true
drivingRouteOverlay.removeFromMap();
drivingRouteOverlay.addToMap();
drivingRouteOverlay.zoomToSpan();
aMap.moveCamera(CameraUpdateFactory.zoomTo(12));
for (int i = 0; i < drivePath.getSteps().size(); i++) {
mList.add( drivePath.getSteps().get(i).getInstruction());
}
mStepAdapter.notifyDataSetChanged();
}