高德地圖導航和路徑規劃

Rx_Re發表於2018-11-19

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;
        }

    }
複製程式碼

相關文章