百度地圖_路線規劃的實作
前言
從小白一步步開始,很多資源是很久以前的,而且沒有操作配套截圖和資源分享。現在本踩過了很多坑,現在開發完成後決定重新寫一份教程,希望能借此幫助到許多其他有這方面需求的人。
精力有限,會盡可能詳細。
本文同項目同步完成,已經是做過好幾個類似項目工程,但還是出了一些小問題,已經附上解決方法,本文中所用到資源檔案已經附上下載下傳連結,也可以自行去百度地圖開發者官網去下載下傳,不過由于版本更新很快,若使用本文開發還是強烈推薦使用本文提供連結進行下載下傳,尤其是SDK,如果在建構項目中出一些問題很可能是SDK已經被官方更新導緻,本文的操作步驟隻在本人開發時保證有效,随着時間推移可能已經不适合,本人也不可能一直維護更新操作步驟。
另外,源碼已在文末給出下載下傳位址,若導入源碼出現問題很大程度上可以考慮是Android Studio(AS)和Gradle版本的問題,請自行百度去解決。
還想說的是,若可以編譯生成了APK,在虛拟機或實體裝置運作中出現問題,給大家分享的一些本人開發百度地圖調試的主要思路:
1.首先請自行百度學習一下AS的BUG調試,同其他的IDE程式一樣,AS也可以辨別代碼運作到哪一步出現問題
2.找到出問題的代碼,BUG調試裡會有報錯原因提示,可以直接複制報錯原因,百度查找解決方法,大機率會有類似的解決文章
相信按照本文可以解決絕大數問題,每個人的開發運作環境不同,不可避免會出一些其他問題,若還有其他問題,本人隻能提供一些建議,具體措施可能還是需要你自己去解決,若分享連結失效,文末附上了**聯系方式(會及時檢視好友申請,同時請注明添加理由,否則不通過申請)**或者評論區冒泡。
于2020.3.7 19:16更新了失效連結,重新編輯了前言
注:
本文僅在前文的基礎上隻新增了步行規劃,其實隻要搞懂原理,隻不過把路線規劃其他抽象方法進行實作而已,這裡僅舉例實作步行規劃的抽象方法。下文會具體指出在哪裡實作抽象方法。
注:
路線規劃的發起不能放到onCreate中,是以做了路線規劃按鈕。
參考官方文檔(步行規劃)步驟:
其實參考價值比較小,隻提供了所需要的MainActivity部分代碼,具體所需要的類方法以及繪制路線的覆寫物資源都沒有提供,一路磕磕絆絆找了好多資源最後實作了路線規劃,現分享如下(另外也可以去官方平台下載下傳官方Demo點選下載下傳進行參考,下面用到的資源其實也是官方的資源):
布局檔案更新:
<Button
android:id="@+id/but_RoutrPlan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="規劃"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="50dp"/>
MainActivity檔案更新(類包會自動導入):
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private MapView mMapView = null;
private BaiduMap mBaiduMap = null;
private Context context;
//定位相關
private double mLatitude;
private double mLongtitude;
//方向傳感器
private MyOrientationListener mMyOrientationListener;
private float mCurrentX;
//自定義圖示
private BitmapDescriptor mIconLocation;
private LocationClient mLocationClient;
public BDAbstractLocationListener myListener;
private LatLng mLastLocationData;
private boolean isFirstin = true;
// 路線規劃相關
private RoutePlanSearch mSearch = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
SDKInitializer.setCoordType(CoordType.BD09LL);
this.context = this;
mMapView = (MapView) findViewById(R.id.bmapView);
//擷取地圖控件引用
mBaiduMap = mMapView.getMap();
initMyLocation();
initPoutePlan();
button();
}
protected void onStart() {
super.onStart();
//開啟定位
mBaiduMap.setMyLocationEnabled(true);
if (!mLocationClient.isStarted())
mLocationClient.start();
//開啟方向傳感器
mMyOrientationListener.start();
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
//停止定位
mBaiduMap.setMyLocationEnabled(false);
mLocationClient.stop();
//停止方向傳感器
mMyOrientationListener.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
mSearch.destroy();
}
@Override
public void onClick(View v) {
SDKInitializer.initialize(getApplicationContext());
switch (v.getId()) {
case R.id.but_Loc: {
centerToMyLocation(mLatitude, mLongtitude);
break;
}
case R.id.but_RoutrPlan: {
StarRoute();
break;
}
}
}
//按鈕響應
private void button() {
//按鈕
Button mbut_Loc = (Button) findViewById(R.id.but_Loc);
Button mbut_RoutrPlan = (Button) findViewById(R.id.but_RoutrPlan);
//按鈕處理
mbut_Loc.setOnClickListener(this);
mbut_RoutrPlan.setOnClickListener(this);
}
//定位
private class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//mapView 銷毀後不在處理新接收的位置
if (location == null || mMapView == null){
return;
}
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此處設定開發者擷取到的方向資訊,順時針0-360
.direction(mCurrentX).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
mBaiduMap.setMyLocationData(locData);
//設定自定義圖示
MyLocationConfiguration config = new
MyLocationConfiguration(
MyLocationConfiguration.LocationMode.NORMAL, true, mIconLocation);
mBaiduMap.setMyLocationConfiguration(config);
//更新經緯度
mLatitude = location.getLatitude();
mLongtitude = location.getLongitude();
//設定起點
mLastLocationData = new LatLng(mLatitude, mLongtitude);
if (isFirstin) {
centerToMyLocation(location.getLatitude(), location.getLongitude());
if (location.getLocType() == BDLocation.TypeGpsLocation) {
// GPS定位結果
Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
// 網絡定位結果
Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
// 離線定位結果
Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeServerError) {
Toast.makeText(context, "定位:伺服器錯誤", Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeNetWorkException) {
Toast.makeText(context, "定位:網絡錯誤", Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeCriteriaException) {
Toast.makeText(context, "定位:手機模式錯誤,請檢查是否飛行", Toast.LENGTH_SHORT).show();
}
isFirstin = false;
}
}
}
//初始化定位
private void initMyLocation() {
//縮放地圖
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
mBaiduMap.setMapStatus(msu);
//開啟定位
mBaiduMap.setMyLocationEnabled(true);
//聲明LocationClient類
mLocationClient = new LocationClient(this);
//通過LocationClientOption設定LocationClient相關參數
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打開gps
option.setCoorType("bd09ll"); // 設定坐标類型
option.setIsNeedAddress(true);//設定是否需要位址資訊
option.setScanSpan(1000);
//設定locationClientOption
mLocationClient.setLocOption(option);
myListener = new MyLocationListener();
//注冊監聽函數
mLocationClient.registerLocationListener(myListener);
//初始化圖示
mIconLocation = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps);
initOrientation();
//開始定位
mLocationClient.start();
}
//回到定位中心
private void centerToMyLocation(double latitude, double longtitude) {
mBaiduMap.clear();
mLastLocationData = new LatLng(latitude, longtitude);
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(mLastLocationData);
mBaiduMap.animateMapStatus(msu);
}
//傳感器
private void initOrientation() {
//傳感器
mMyOrientationListener = new MyOrientationListener(context);
mMyOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mCurrentX = x;
}
});
}
//路線規劃初始化
private void initPoutePlan() {
mSearch = RoutePlanSearch.newInstance();
mSearch.setOnGetRoutePlanResultListener(listener);
}
// 路線規劃子產品
public OnGetRoutePlanResultListener listener = new OnGetRoutePlanResultListener() {
@Override
public void onGetWalkingRouteResult(WalkingRouteResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
Toast.makeText(MainActivity.this, "路線規劃:未找到結果,檢查輸入", Toast.LENGTH_SHORT).show();
//禁止定位
isFirstin = false;
}
assert result != null;
if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {
// 起終點或途經點位址有岐義,通過以下接口擷取建議查詢資訊
result.getSuggestAddrInfo();
return;
}
if (result.error == SearchResult.ERRORNO.NO_ERROR) {
mBaiduMap.clear();
Toast.makeText(MainActivity.this, "路線規劃:搜尋完成", Toast.LENGTH_SHORT).show();
WalkingRouteOverlay overlay = new WalkingRouteOverlay(mBaiduMap);
overlay.setData(result.getRouteLines().get(0));
overlay.addToMap();
overlay.zoomToSpan();
}
//禁止定位
isFirstin = false;
}
@Override
public void onGetTransitRouteResult(TransitRouteResult var1) {
}
@Override
public void onGetMassTransitRouteResult(MassTransitRouteResult var1) {
}
@Override
public void onGetDrivingRouteResult(DrivingRouteResult result) {
}
@Override
public void onGetIndoorRouteResult(IndoorRouteResult var1) {
}
@Override
public void onGetBikingRouteResult(BikingRouteResult var1) {
}
};
//開始規劃
private void StarRoute() {
SDKInitializer.initialize(getApplicationContext());
// 設定起、終點資訊
PlanNode stNode = PlanNode.withCityNameAndPlaceName("北京", "西二旗地鐵站");
PlanNode enNode = PlanNode.withCityNameAndPlaceName("北京", "百度科技園");
mSearch.walkingSearch((new WalkingRoutePlanOption())
.from(stNode)
.to(enNode));
}
}
更新完代碼會有如下報錯提示:
這就是因為缺乏相應的類包:
這裡附上百度網盤連結: 規劃資源包提取碼:b73i
選中com包,複制到工程java目錄下,會自動展開為如下結構:
報錯處理:
R報錯(有幾處改幾處,改成自己的包名的R):
直接删除,一般會自動引入正确的R:
R下的資源報錯(資源在上邊的連結):
(1)layout報錯:
需要在上圖路徑下添加對應檔案:
添加後:
(2)Style報錯:
用下面檔案進行替換:
替換前:
替換後:
以上報錯解決完成後:
在以下assets目錄下添加資源:
資源檔案:
添加後:
至此,路線規劃完成了引入,效果如下:
點選按鈕後:
附加:
其他類型規劃的實作,需要在如下代碼處進行實作:
已經實作的步行規劃:
還需要實作的部分:
在實作了上述抽象方法以後,在下圖代碼處進行做對應修改即可實作相應類型的路線規劃:
工程按照步驟是能自己建好自己工程項目的,有問題評論區回複,或者本人的qq:1587128132。
工程開發,文章撰寫耗費不少精力,很多資源收集不易。若需要源碼,給出源碼下載下傳連結(按需下載下傳,前一節功能被後一節包含,需要全部功能的朋友直接下載下傳最後一節【導航和TTS】的源碼即可):
源碼
生成的可運作apk:app-debug.apk 提取碼:dy7h