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;
}
}
複製程式碼