上一篇文章,我們知道了如何集成百度地圖并且顯示出來,那么這一篇文章我們就來看看如何對百度地圖進行需要的設(shè)置以及定位并且顯示當前的位置。
一、android集成百度地圖(android百度地圖SDK系列)
二、android百度地圖定位顯示當前位置(android百度地圖SDK系列)
三、android百度地圖覆蓋物(android百度地圖SDK系列)
一、百度地圖基本的配置
我們知道,一個最基本的地圖是肯定滿足不了我們的需求的,所以就要進行一些設(shè)置,來改變地圖。
首先我們看最基本的:
//地圖控件
private MapView mapView;
//百度地圖
private BaiduMap baiduMap;
/**
* 初始化控件
*/
public void initView(){
mapView = (MapView)findViewById(R.id.mapView);
}
/**
* 初始化地圖
*/
public void initMap(){
//得到地圖實例
baiduMap = mapView.getMap();
/*
設(shè)置地圖類型
*/
//普通地圖
baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
//衛(wèi)星地圖
//baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
//空白地圖, 基礎(chǔ)地圖瓦片將不會被渲染。在地圖類型中設(shè)置為NONE,將不會使用流量下載基礎(chǔ)地圖瓦片圖層。使用場景:與瓦片圖層一起使用,節(jié)省流量,提升自定義瓦片圖下載速度。
//baiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);
//開啟交通圖
baiduMap.setTrafficEnabled(true);
//關(guān)閉縮放按鈕
mapView.showZoomControls(false);
}
以上代碼就是最基本的設(shè)置了,很簡單的樣子,所以不過多停留在此。
二、定位與顯示中心點
說到定位,不得不提起android6.0的動態(tài)權(quán)限,如果版本小于6.0則不會有問題,一旦大于等于6.0直接定位就不行了,必須要申請動態(tài)權(quán)限,所以在這里我就直接將動態(tài)權(quán)限簡單的說一下。不過大家都知道因為國內(nèi)很多廠商對android系統(tǒng)進行所謂的包殼,所以我們永遠也摸不清這些殼的尿性,因此在這里是選擇了PermissionsDispatcher第三方權(quán)限框架來做。
下面我們就來看看它的用法:
首先在build.gradle里加入依賴
compile 'com.github.hotchemi:permissionsdispatcher:2.2.0'
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.2.0'
依賴成功后我們先要看看它的幾個注解和方法:
@NeedsPermission:申請權(quán)限成功時
@OnShowRationale:申請權(quán)限告訴用戶原因時
@OnPermissionDenied:申請權(quán)限被拒絕時
@OnNeverAskAgain:申請權(quán)限被拒絕并勾選不再提醒時
@RuntimePermissions:注釋此Activity或Fragment,在Make project生成類時會用到
onRequestPermissionsResult:回調(diào)方法
首先我們對需要定位權(quán)限的當前Activity類加上@RuntimePermissions注解:
@RuntimePermissions
public class MainActivity extends AppCompatActivity {}
下面我們使用上面剩下的注解和方法來完成對權(quán)限的動態(tài)申請:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// NOTE: delegate the permission handling to generated method
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
/**
* 申請權(quán)限成功時
*/
@NeedsPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
void ApplySuccess() {
}
/**
* 申請權(quán)限告訴用戶原因時
* @param request
*/
@OnShowRationale(Manifest.permission.ACCESS_COARSE_LOCATION)
void showRationaleForMap(PermissionRequest request) {
showRationaleDialog("使用此功能需要打開定位的權(quán)限", request);
}
/**
* 申請權(quán)限被拒絕時
*
*/
@OnPermissionDenied(Manifest.permission.ACCESS_COARSE_LOCATION)
void onMapDenied() {
Toast.makeText(this,"你拒絕了權(quán)限,該功能不可用",Toast.LENGTH_LONG).show();
}
/**
* 申請權(quán)限被拒絕并勾選不再提醒時
*/
@OnNeverAskAgain(Manifest.permission.ACCESS_COARSE_LOCATION)
void onMapNeverAskAgain() {
AskForPermission();
}
/**
* 告知用戶具體需要權(quán)限的原因
* @param messageResId
* @param request
*/
private void showRationaleDialog(String messageResId, final PermissionRequest request) {
new AlertDialog.Builder(this)
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(@NonNull DialogInterface dialog, int which) {
request.proceed();//請求權(quán)限
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(@NonNull DialogInterface dialog, int which) {
request.cancel();
}
})
.setCancelable(false)
.setMessage(messageResId)
.show();
}
/**
* 被拒絕并且不再提醒,提示用戶去設(shè)置界面重新打開權(quán)限
*/
private void AskForPermission() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("當前應(yīng)用缺少定位權(quán)限,請去設(shè)置界面打開\n打開之后按兩次返回鍵可回到該應(yīng)用哦");
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
});
builder.setPositiveButton("設(shè)置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + MainActivity.this.getPackageName())); // 根據(jù)包名打開對應(yīng)的設(shè)置界面
startActivity(intent);
}
});
builder.create().show();
}
我們可以看到其中四個注解后面跟得有參數(shù),這個參數(shù)就是我們需要申請的權(quán)限。然后在onRequestPermissionsResult里出現(xiàn)了以下一句代碼:
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
這句代碼里的類和方法是沒有的,它是通過對Activity或者Fragment@RuntimePermissions注解后并且進行Make project后才出現(xiàn)的。
至此,定位權(quán)限的動態(tài)申請就搞定了,上面只是該框架的簡單用法。更加全面的文檔:PermissionsDispatcher
既然權(quán)限搞定了,那么我們就可以一鼓作氣的完成的定位并顯示了。
1.我們在之前的InitMap方法里加上以下代碼:
// 開啟定位圖層
baiduMap.setMyLocationEnabled(true);
//聲明LocationClient類
mLocationClient = new LocationClient(this);
//注冊監(jiān)聽函數(shù)
mLocationClient.registerLocationListener(myListener);
initLocation();
//開始定位
mLocationClient.start();
2.聲明一些需要的變量,配置定位參數(shù),實現(xiàn)定位監(jiān)聽方法,設(shè)置中心點和marker
//防止每次定位都重新設(shè)置中心點和marker
private boolean isFirstLocation = true;
//初始化LocationClient定位類
private LocationClient mLocationClient = null;
//BDAbstractLocationListener為7.2版本新增的Abstract類型的監(jiān)聽接口,原有BDLocationListener接口
private BDLocationListener myListener = new MyLocationListener();
//經(jīng)緯度
private double lat;
private double lon;
/**
* 配置定位參數(shù)
*/
private void initLocation() {
LocationClientOption option = new LocationClientOption();
//可選,默認高精度,設(shè)置定位模式,高精度,低功耗,僅設(shè)備
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可選,默認gcj02,設(shè)置返回的定位結(jié)果坐標系
option.setCoorType("bd09ll");
//可選,默認0,即僅定位一次,設(shè)置發(fā)起定位請求的間隔需要大于等于1000ms才是有效的
int span = 5000;
option.setScanSpan(span);
//可選,設(shè)置是否需要地址信息,默認不需要
option.setIsNeedAddress(true);
//可選,默認false,設(shè)置是否使用gps
option.setOpenGps(true);
//可選,默認false,設(shè)置是否當GPS有效時按照1S/1次頻率輸出GPS結(jié)果
option.setLocationNotify(true);
//可選,默認false,設(shè)置是否需要位置語義化結(jié)果,可以在BDLocation.getLocationDescribe里得到,結(jié)果類似于“在北京天安門附近”
option.setIsNeedLocationDescribe(true);
//可選,默認false,設(shè)置是否需要POI結(jié)果,可以在BDLocation.getPoiList里得到
option.setIsNeedLocationPoiList(true);
//可選,默認true,定位SDK內(nèi)部是一個SERVICE,并放到了獨立進程,設(shè)置是否在stop的時候殺死這個進程,默認不殺死
option.setIgnoreKillProcess(false);
//可選,默認false,設(shè)置是否收集CRASH信息,默認收集
option.SetIgnoreCacheException(false);
//可選,默認false,設(shè)置是否需要過濾GPS仿真結(jié)果,默認需要
option.setEnableSimulateGps(false);
mLocationClient.setLocOption(option);
}
/**
* 實現(xiàn)定位監(jiān)聽 位置一旦有所改變就會調(diào)用這個方法
* 可以在這個方法里面獲取到定位之后獲取到的一系列數(shù)據(jù)
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//獲取定位結(jié)果
location.getTime(); //獲取定位時間
location.getLocationID(); //獲取定位唯一ID,v7.2版本新增,用于排查定位問題
location.getLocType(); //獲取定位類型
location.getLatitude(); //獲取緯度信息
location.getLongitude(); //獲取經(jīng)度信息
location.getRadius(); //獲取定位精準度
location.getAddrStr(); //獲取地址信息
location.getCountry(); //獲取國家信息
location.getCountryCode(); //獲取國家碼
location.getCity(); //獲取城市信息
location.getCityCode(); //獲取城市碼
location.getDistrict(); //獲取區(qū)縣信息
location.getStreet(); //獲取街道信息
location.getStreetNumber(); //獲取街道碼
location.getLocationDescribe(); //獲取當前位置描述信息
location.getPoiList(); //獲取當前位置周邊POI信息
location.getBuildingID(); //室內(nèi)精準定位下,獲取樓宇I(lǐng)D
location.getBuildingName(); //室內(nèi)精準定位下,獲取樓宇名稱
location.getFloor(); //室內(nèi)精準定位下,獲取當前位置所處的樓層信息
//經(jīng)緯度
lat = location.getLatitude();
lon = location.getLongitude();
//這個判斷是為了防止每次定位都重新設(shè)置中心點和marker
if (isFirstLocation) {
isFirstLocation = false;
//設(shè)置并顯示中心點
setPosition2Center(baiduMap, location, true);
}
}
}
/**
* 設(shè)置中心點和添加marker
*
* @param map
* @param bdLocation
* @param isShowLoc
*/
public void setPosition2Center(BaiduMap map, BDLocation bdLocation, Boolean isShowLoc) {
MyLocationData locData = new MyLocationData.Builder()
.accuracy(bdLocation.getRadius())
.direction(bdLocation.getRadius()).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();
map.setMyLocationData(locData);
if (isShowLoc) {
LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(ll).zoom(18.0f);
map.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
}
}
3.最后我們在onCreate方法里進行android版本的判斷,根據(jù)android版本來決定直接定位顯示還是需要動態(tài)權(quán)限以及需要在權(quán)限申請成功的方法里調(diào)用initMap方法和生命周期的管理,代碼如下:
//當android系統(tǒng)小于5.0的時候直接定位顯示,不用動態(tài)申請權(quán)限
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
initMap();
} else {
MainActivityPermissionsDispatcher.ApplySuccessWithCheck(this);
}
/**
* 申請權(quán)限成功時
*/
@NeedsPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
void ApplySuccess() {
initMap();
}
@Override
public void onResume() {
super.onResume();
//在activity執(zhí)行onResume時執(zhí)行mMapView. onResume (),實現(xiàn)地圖生命周期管理
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
//在activity執(zhí)行onPause時執(zhí)行mMapView. onPause (),實現(xiàn)地圖生命周期管理
mapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
//在activity執(zhí)行onDestroy時執(zhí)行mMapView.onDestroy(),實現(xiàn)地圖生命周期管理
// 退出時銷毀定位
mLocationClient.unRegisterLocationListener(myListener);
mLocationClient.stop();
// 關(guān)閉定位圖層
baiduMap.setMyLocationEnabled(false);
mapView.onDestroy();
mapView = null;
}
最后我們來看看運行效果


到此為止,android集成百度地圖的定位與顯示當前位置就結(jié)束了,從第一篇文章到第二篇所有的地方我都注釋的比較細,以便新手學習和參考。最后因為我公司的項目中還涉及到了動態(tài)添加點和幾何圖形覆蓋物,所以還有有一篇結(jié)尾的文章,大家耐心等待~