天天看點

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

百度地圖_路線規劃的實作

前言

從小白一步步開始,很多資源是很久以前的,而且沒有操作配套截圖和資源分享。現在本踩過了很多坑,現在開發完成後決定重新寫一份教程,希望能借此幫助到許多其他有這方面需求的人。

精力有限,會盡可能詳細。

本文同項目同步完成,已經是做過好幾個類似項目工程,但還是出了一些小問題,已經附上解決方法,本文中所用到資源檔案已經附上下載下傳連結,也可以自行去百度地圖開發者官網去下載下傳,不過由于版本更新很快,若使用本文開發還是強烈推薦使用本文提供連結進行下載下傳,尤其是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"/>
           
2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

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

}

更新完代碼會有如下報錯提示:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

這就是因為缺乏相應的類包:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

這裡附上百度網盤連結: 規劃資源包提取碼:b73i

選中com包,複制到工程java目錄下,會自動展開為如下結構:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

報錯處理:

R報錯(有幾處改幾處,改成自己的包名的R):

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

直接删除,一般會自動引入正确的R:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

R下的資源報錯(資源在上邊的連結):

(1)layout報錯:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

需要在上圖路徑下添加對應檔案:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

添加後:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

(2)Style報錯:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

用下面檔案進行替換:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

替換前:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

替換後:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

以上報錯解決完成後:

在以下assets目錄下添加資源:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

資源檔案:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

添加後:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

至此,路線規劃完成了引入,效果如下:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

點選按鈕後:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

附加:

其他類型規劃的實作,需要在如下代碼處進行實作:

已經實作的步行規劃:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

還需要實作的部分:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

在實作了上述抽象方法以後,在下圖代碼處進行做對應修改即可實作相應類型的路線規劃:

2019超詳細Android Studio新手開發百度地圖(4)—百度地圖_路線規劃的實作百度地圖_路線規劃的實作

工程按照步驟是能自己建好自己工程項目的,有問題評論區回複,或者本人的qq:1587128132。

工程開發,文章撰寫耗費不少精力,很多資源收集不易。若需要源碼,給出源碼下載下傳連結(按需下載下傳,前一節功能被後一節包含,需要全部功能的朋友直接下載下傳最後一節【導航和TTS】的源碼即可):

源碼

生成的可運作apk:app-debug.apk 提取碼:dy7h