這是基于百度地圖sdk的地圖app開發系列部落格第四篇
代碼倉庫位置:https://github.com/YanhuiLu89/lmap.git
上一篇 基于百度地圖sdk的地圖app開發(三)——優化地圖顯示
下一篇基于百度地圖sdk的地圖app開發(五)——poi檢索
因為本人是做C++開發,android和java都不熟,這方面知識有說錯或者不好的習慣,歡迎賜較。
官方參考文檔顯示定位
地圖預設是在北京天安門位置,我們要把它定位到目前我們的實際位置。
1 配置AndroidManifest.xml檔案
加入權限聲明,如下
<!-- 這個權限用于進行網絡定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 這個權限用于通路GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
在Application标簽中聲明定位的service元件
<service android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote"/>
2 開啟地圖的定位圖層
在MainActivity的onCreate函數開啟地圖的定位圖層
//擷取地圖控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
//開啟定位
mMapView.getMap().setMyLocationEnabled(true);
3 構造地圖資料
将MainActivity類中添加内部類MyLocationListener繼承自BDAbstractListener并重寫其onReceieveLocation方法來擷取定位資料,并将其傳給MapView。
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//mapView 銷毀後不在處理新接收的位置
if (bdLocation == null || mMapView == null){
return;
}
mCurLocation=bdLocation;//儲存目前定位,後面檢索算路要用
int type=bdLocation.getLocType();
MyLocationData locData = new MyLocationData.Builder()
.accuracy(bdLocation.getRadius())
// 此處設定開發者擷取到的方向資訊,順時針0-360
.direction(bdLocation.getDirection()).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();
BaiduMap bmap=mMapView.getMap();
bmap.setMyLocationData(locData);
}
4 通過LocationClient發起定位
在MainActivity中添加成員變量mLocationClient代碼如下
private LocationClient mLocationClient=null;
在onCreate函數中 ,初始化定位,開啟定位,代碼如下
//定位初始化
mLocationClient = new LocationClient(this);
//通過LocationClientOption設定LocationClient相關參數
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打開gps
option.setIsNeedAddress(true);
option.setCoorType("bd09ll"); // 設定坐标類型
option.setScanSpan(1000);
//設定locationClientOption
mLocationClient.setLocOption(option);
//注冊LocationListener監聽器
MyLocationListener myLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(myLocationListener);
//開啟地圖定位圖層
mLocationClient.start();
5 添加定位按鈕
我們使用百度地圖或者高德地圖時會用一個常用的場景:拖動地圖,浏覽地圖,之後點選左下角圓圈按鈕,會回到目前位置。下面添加定位按鈕,實作該功能。
往布局中添加定位按鈕,布局代碼如下
<ImageButton
android:id="@+id/mylocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="630dp"
app:srcCompat="@android:drawable/ic_menu_mylocation" />
在定位按鈕的click函數中,發起定位,代碼如下
ImageButton locationBtn=this.findViewById(R.id.mylocation);
locationBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
mLocationClient.start();
}
});
6 銷毀location
在onDestroy函數,mapView銷毀前,銷毀location,代碼如下
@Override
protected void onDestroy() {
super.onDestroy();
//在activity執行onDestroy時執行mMapView.onDestroy(),實作地圖生命周期管理
mLocationClient.stop();
mMapView.getMap().setMyLocationEnabled(false);
mMapView.onDestroy();
}
7遇到定位失敗問題及解決辦法
以上是按照官方文檔一步步開發的,但是完成後遇到了問題:位沒有成功,調試發現獲得經緯度的值都是一個無效的值
調查及解決方法如下
1、bdLocation.getLocType()值為62
在sdk中可以看到62的描述為“"Location failed beacuse we can not get any loc information!”。
原因:是app沒有真正獲得定位權限,去手機設定-》應用-》權限管理-》權限-》位置資訊中,找到app設為應用期間允許。
2、第一步改完後還是定位沒有成功,bdLocation.getLocType()值為505
在sdk中可以看到505的描述為“"NetWork location failed because baidu location service check the key is unlegal, please check the key in AndroidManifest.xml !‘
原因:AndroidManifest.xml中ak寫成了我的另外一個應用的key,改成正确的ak後(下面代碼第2行),type傳回值正确,經緯度也是有效值了。關于ak的擷取請參考 基于百度地圖sdk的地圖app開發(一)——開發環境配置與sdk下載下傳第三部分
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="2IT56XoP7GW3G7saSAtcPq6QhQLVNcjr" />
3、經過上面兩部能獲得有效的經緯度值了,但是地圖還是沒有到我的目前位置
繼續調查發現
原因:通過網上調查需要調用 BadiduMap的animateMapStatus接口,重新刷地圖,另外為了顯示定位效果明顯,設定地圖縮放比例為18級。
解決辦法:修改MyLocationListener代碼,修改後代碼如下,主要添加了當手動定位(即點選定位按鈕)或者第一次定位成功時,縮放比例尺且調用 BadiduMap的animateMapStatus接口
class MyLocationListener extends BDAbstractLocationListener {
private boolean isFirstLoc=true;
private boolean autoLocation=false;
public void setAutoLocation(boolean b){
autoLocation=b;
}
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//mapView 銷毀後不在處理新接收的位置
if (bdLocation == null || mMapView == null){
return;
}
int type=bdLocation.getLocType();
MyLocationData locData = new MyLocationData.Builder()
.accuracy(bdLocation.getRadius())
// 此處設定開發者擷取到的方向資訊,順時針0-360
.direction(bdLocation.getDirection()).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();
BaiduMap bmap=mMapView.getMap();
bmap.setMyLocationData(locData);
/**
*當首次定位或手動發起定位時,記得要放大地圖,便于觀察具體的位置
* LatLng是縮放的中心點,這裡注意一定要和上面設定給地圖的經緯度一緻;
* MapStatus.Builder 地圖狀态構造器
*/
if (isFirstLoc||autoLocation) {
isFirstLoc = false;
autoLocation=false;
LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
MapStatus.Builder builder = new MapStatus.Builder();
//設定縮放中心點;縮放比例;
builder.target(ll).zoom(18.0f);
//給地圖設定狀态
bmap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
}
}
}
另外定位按鈕的click函數中添加設定手動定位标志位,修改後代碼如下
ImageButton locationBtn=this.findViewById(R.id.mylocation);
locationBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
//設定手動定位
myLocationListener.setAutoLocation(true);
//開啟地圖定位圖層
mLocationClient.start();
}
});
最後優化後的app效果如下
第一次啟動時定位到目前位置下圖1,拖動及縮放地圖下圖2,點選左下角Location按鈕下圖3