1 高德地图定位
1.1 要使用路径规划和导航需要使用3Dmap
在build.gradle文件加入一下包
api 'com.amap.api:search:6.5.0.1'
api 'com.amap.api:location:4.3.0'
api 'com.amap.api:navi-3dmap:6.4.0_3dmap6.5.0'
1.2 初始化mapView
private void initAMap() {
if (aMap == null) {
aMap = mapView.getMap();
//地图设置相关
UiSettings settings = aMap.getUiSettings();
//去掉自带的放大缩小按钮
settings.setZoomControlsEnabled(false);
//支持手势缩放地图
settings.setGestureScaleByMapCenter(true);
//地图的触摸事件
aMap.setOnMapTouchListener(this);
//地图加载完的回调事件
aMap.setOnMapLoadedListener(this);
//地图位置变化事件
aMap.setOnCameraChangeListener(this);
//地图点击事件
aMap.setOnMapClickListener(this);
// 绑定 Marker 被点击事件
aMap.setOnMarkerClickListener(markerClickListener);
// 设置自定义InfoWindow样式
aMap.setInfoWindowAdapter(this);
mAMapNavi = AMapNavi.getInstance(getApplicationContext());
mAMapNavi.addAMapNaviListener(this);
}
}
1.3 开启定位相关
public void startLocate() {
mLocationClient = new AMapLocationClient(context);
mLocationClient.setLocationListener(this);
AMapLocationClientOption option=new AMapLocationClientOption();
option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//多次定位获取数据
option.setOnceLocation(false);
option.setInterval(8*1000);
mLocationClient.setLocationOption(option);
mLocationClient.startLocation();
}
1.4 回调到下面的onLocationChanged方法中,你可以使用自定义的回调把定位数据监听回来
@Override
public void onLocationChanged(AMapLocation amapLocation) {
if (amapLocation != null && amapLocation.getErrorCode() == 0) {
PositionEntity entity = new PositionEntity();
entity.latitue = amapLocation.getLatitude();
entity.longitude = amapLocation.getLongitude();
entity.city = amapLocation.getCity();
if (!TextUtils.isEmpty(amapLocation.getAddress())) {
entity.address = amapLocation.getAddress();
}
mOnLocationGetlisGetListener.onLocationGet(entity);
}
}
1.4 监听到对应的onLocationGet方法中,使用一个定位的Marker标识就可以
@Override
public void onLocationGet(PositionEntity entity) {
mStartPosition = new LatLng(entity.latitue, entity.longitude);
if (mIsFirstShow) {
CameraUpdate cameraUpate = CameraUpdateFactory.newLatLngZoom(
mStartPosition, 17);
aMap.animateCamera(cameraUpate);
mIsFirstShow = false;
}
mInitialMark.setPosition(mStartPosition);
processSearchTips(entity);
}
这样就完成对应的定位信息
2.路径规划
2.1获取路径规划起始位置和终点位置的经纬度
起始信息直接使用定位的当前位置信息
对应的终点信息,可以使用随机数来确定
public static void addEmulateData(AMap amap, LatLng center) {
if (markers.size() == 0) {
//终点位置信息的标识
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory
.fromResource(R.drawable.stable_cluster_marker_one_normal);
for (int i = 0; i < 20; i++) {
double latitudeDelt;
double longtitudeDelt;
if (i % 2 == 0) {
latitudeDelt = (Math.random() - 0.5) * 0.1;
longtitudeDelt = (Math.random() - 0.5) * 0.1;
} else {
latitudeDelt = (Math.random() - 0.5) * 0.01;
longtitudeDelt = (Math.random() - 0.5) * 0.01;
}
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.icon(bitmapDescriptor);
markerOptions.position(
new LatLng(center.latitude + latitudeDelt, center.longitude + longtitudeDelt));
Marker marker = amap.addMarker(markerOptions);
markers.add(marker);
}
} else {
for (Marker marker : markers) {
double latitudeDelt = (Math.random() - 0.5) * 0.1;
double longtitudeDelt = (Math.random() - 0.5) * 0.1;
marker.setPosition(
new LatLng(center.latitude + latitudeDelt, center.longitude + longtitudeDelt));
}
}
}
2.2 设置marker的点击事件,动态计算对应的路线
AMap.OnMarkerClickListener markerClickListener = new AMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(final Marker marker) {
LogUtils.w("点击的Marker");
LogUtils.w(marker.getPosition() + "");
isClickIdentification = true;
//清除原先的路径
clearRoute();
//增加动画
startAnim(marker);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(300);
tempMark = marker;
mStartPoint = new LatLonPoint(mRecordPositon.latitude, mRecordPositon.longitude);
startList.add(new NaviLatLng(mRecordPositon.latitude, mRecordPositon.longitude));
mPositionMark.setPosition(mRecordPositon);
mEndPoint = new LatLonPoint(marker.getPosition().latitude,
marker.getPosition().longitude);
handleEndList(mEndPoint);
//规划路径
planRoute();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return true;
}
};
2.3 路径规划路径选择
调用以下事件就可以,在对应的onCalculateRouteSuccess会返回对应的路径
mAMapNavi.calculateRideRoute(startList.get(0), endList.get(0));
返回的路径会存在多条,每个对应进行处理即可
@Override
public void onCalculateRouteSuccess(int[] ints) {
if (ints.length == 1) {
onCalculateRouteSuccessOld();
} else {
onCalculateMultipleRoutesSuccessOld(ints);
}
}
private void onCalculateRouteSuccessOld() {
/**
* 清空上次计算的路径列表。
*/
routeOverlays.clear();
ways.clear();
AMapNaviPath path = mAMapNavi.getNaviPath();
/**
* 单路径不需要进行路径选择,直接传入-1即可
*/
drawRoutes(-1, path);
showMarkInfo(path);
}
private void onCalculateMultipleRoutesSuccessOld(int[] ints) {
//清空上次计算的路径列表。
routeOverlays.clear();
ways.clear();
HashMap<Integer, AMapNaviPath> paths = mAMapNavi.getNaviPaths();
for (int i = 0; i < ints.length; i++) {
AMapNaviPath path = paths.get(ints[i]);
if (path != null) {
drawRoutes(ints[i], path);
ways.add(path);
}
}
changeRoute();
}
2.4 路径规划画线
画线其实也就是调用高德的api即可
/**
* 绘制路线
*/
private void drawRoutes(int routeId, AMapNaviPath path) {
calculateSuccess = true;
aMap.moveCamera(CameraUpdateFactory.changeTilt(0));
//路径绘制图层
RouteOverLay routeOverLay = new RouteOverLay(aMap, path, this);
routeOverLay.setTrafficLine(false);
routeOverLay.addToMap();
routeOverlays.put(routeId, routeOverLay);
}
3 实时导航
导航其实只要调用AMapNavi的startNavi即可
mAMapNaviView.setAMapNaviViewListener(this);
//获取AMapNavi实例
mAMapNavi = AMapNavi.getInstance(this);
//添加监听回调,用于处理算路成功
mAMapNavi.addAMapNaviListener(this);
//实例化语音引擎
mTtsManager = TTSController.getInstance(getApplicationContext());
mTtsManager.init();
mAMapNavi.addAMapNaviListener(mTtsManager);
mAMapNavi.startNavi(NaviType.GPS);
3.1 加入讯飞语音导航
需要实现AMapNaviListener接口,一般处理下面几个接口就可以了
@Override
public void onCalculateRouteFailure(int arg0) {
if (wordList != null)
wordList.addLast("路线规划失败");
}
@Override
public void onGetNavigationText(int arg0, String arg1) {
//导航相关的语音播报
if (wordList != null)
wordList.addLast(arg1);
handler.obtainMessage(CHECK_TTS_PLAY).sendToTarget();
}
@Override
public void onReCalculateRouteForTrafficJam() {
if (wordList != null)
wordList.addLast("前方路线拥堵,路线重新规划");
}
@Override
public void onReCalculateRouteForYaw() {
if (wordList != null)
wordList.addLast("路线重新规划");
}
回调需要是用Handler来处理,主要是播报方式是队列模式。其原理就是依次将需要播报的语音放入链表中,播报过程是从头开始依次往后播报
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case TTS_PLAY:
synchronized (mTts) {
if (!isPlaying && mTts != null && wordList.size() > 0) {
isPlaying = true;
String playtts = wordList.removeFirst();
if (mTts == null) {
createSynthesizer();
}
mTts.startSpeaking(playtts, new SynthesizerListener() {
@Override
public void onCompleted(SpeechError arg0) {
isPlaying = false;
handler.obtainMessage(1).sendToTarget();
}
@Override
public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
}
@Override
public void onBufferProgress(int arg0, int arg1, int arg2, String arg3) {
// 合成进度
isPlaying = true;
}
@Override
public void onSpeakBegin() {
//开始播放
isPlaying = true;
}
@Override
public void onSpeakPaused() {
}
@Override
public void onSpeakProgress(int arg0, int arg1, int arg2) {
//播放进度
isPlaying = true;
}
@Override
public void onSpeakResumed() {
//继续播放
isPlaying = true;
}
});
}
}
break;
case CHECK_TTS_PLAY:
if (!isPlaying) {
handler.obtainMessage(1).sendToTarget();
}
break;
}
}