上一篇文章脾拆,我們知道了如何集成百度地圖并且顯示出來,那么這一篇文章我們就來看看如何對(duì)百度地圖進(jìn)行需要的設(shè)置以及定位并且顯示當(dāng)前的位置莹妒。
一名船、android集成百度地圖(android百度地圖SDK系列)
二、android百度地圖定位顯示當(dāng)前位置(android百度地圖SDK系列)
三旨怠、android百度地圖覆蓋物(android百度地圖SDK系列)
一渠驼、百度地圖基本的配置
我們知道,一個(gè)最基本的地圖是肯定滿足不了我們的需求的鉴腻,所以就要進(jìn)行一些設(shè)置迷扇,來改變地圖百揭。
首先我們看最基本的:
//地圖控件
private MapView mapView;
//百度地圖
private BaiduMap baiduMap;
/**
* 初始化控件
*/
public void initView(){
mapView = (MapView)findViewById(R.id.mapView);
}
/**
* 初始化地圖
*/
public void initMap(){
//得到地圖實(shí)例
baiduMap = mapView.getMap();
/*
設(shè)置地圖類型
*/
//普通地圖
baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
//衛(wèi)星地圖
//baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
//空白地圖, 基礎(chǔ)地圖瓦片將不會(huì)被渲染。在地圖類型中設(shè)置為NONE蜓席,將不會(huì)使用流量下載基礎(chǔ)地圖瓦片圖層器一。使用場(chǎng)景:與瓦片圖層一起使用,節(jié)省流量厨内,提升自定義瓦片圖下載速度祈秕。
//baiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);
//開啟交通圖
baiduMap.setTrafficEnabled(true);
//關(guān)閉縮放按鈕
mapView.showZoomControls(false);
}
以上代碼就是最基本的設(shè)置了,很簡(jiǎn)單的樣子雏胃,所以不過多停留在此请毛。
二、定位與顯示中心點(diǎn)
說到定位瞭亮,不得不提起android6.0的動(dòng)態(tài)權(quán)限方仿,如果版本小于6.0則不會(huì)有問題,一旦大于等于6.0直接定位就不行了统翩,必須要申請(qǐng)動(dòng)態(tài)權(quán)限仙蚜,所以在這里我就直接將動(dòng)態(tài)權(quán)限簡(jiǎn)單的說一下。不過大家都知道因?yàn)閲?guó)內(nèi)很多廠商對(duì)android系統(tǒng)進(jìn)行所謂的包殼厂汗,所以我們永遠(yuǎn)也摸不清這些殼的尿性鳍征,因此在這里是選擇了PermissionsDispatcher第三方權(quán)限框架來做。
下面我們就來看看它的用法:
首先在build.gradle里加入依賴
compile 'com.github.hotchemi:permissionsdispatcher:2.2.0'
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.2.0'
依賴成功后我們先要看看它的幾個(gè)注解和方法:
@NeedsPermission:申請(qǐng)權(quán)限成功時(shí)
@OnShowRationale:申請(qǐng)權(quán)限告訴用戶原因時(shí)
@OnPermissionDenied:申請(qǐng)權(quán)限被拒絕時(shí)
@OnNeverAskAgain:申請(qǐng)權(quán)限被拒絕并勾選不再提醒時(shí)
@RuntimePermissions:注釋此Activity或Fragment面徽,在Make project生成類時(shí)會(huì)用到
onRequestPermissionsResult:回調(diào)方法
首先我們對(duì)需要定位權(quán)限的當(dāng)前Activity類加上@RuntimePermissions注解:
@RuntimePermissions
public class MainActivity extends AppCompatActivity {}
下面我們使用上面剩下的注解和方法來完成對(duì)權(quán)限的動(dòng)態(tài)申請(qǐng):
@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);
}
/**
* 申請(qǐng)權(quán)限成功時(shí)
*/
@NeedsPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
void ApplySuccess() {
}
/**
* 申請(qǐng)權(quán)限告訴用戶原因時(shí)
* @param request
*/
@OnShowRationale(Manifest.permission.ACCESS_COARSE_LOCATION)
void showRationaleForMap(PermissionRequest request) {
showRationaleDialog("使用此功能需要打開定位的權(quán)限", request);
}
/**
* 申請(qǐng)權(quán)限被拒絕時(shí)
*
*/
@OnPermissionDenied(Manifest.permission.ACCESS_COARSE_LOCATION)
void onMapDenied() {
Toast.makeText(this,"你拒絕了權(quán)限艳丛,該功能不可用",Toast.LENGTH_LONG).show();
}
/**
* 申請(qǐng)權(quán)限被拒絕并勾選不再提醒時(shí)
*/
@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();//請(qǐng)求權(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("當(dāng)前應(yīng)用缺少定位權(quán)限,請(qǐng)去設(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ù)包名打開對(duì)應(yīng)的設(shè)置界面
startActivity(intent);
}
});
builder.create().show();
}
我們可以看到其中四個(gè)注解后面跟得有參數(shù),這個(gè)參數(shù)就是我們需要申請(qǐng)的權(quán)限趟紊。然后在onRequestPermissionsResult里出現(xiàn)了以下一句代碼:
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
這句代碼里的類和方法是沒有的氮双,它是通過對(duì)Activity或者Fragment@RuntimePermissions注解后并且進(jìn)行Make project后才出現(xiàn)的。
至此霎匈,定位權(quán)限的動(dòng)態(tài)申請(qǐng)就搞定了戴差,上面只是該框架的簡(jiǎn)單用法。更加全面的文檔:PermissionsDispatcher
既然權(quán)限搞定了铛嘱,那么我們就可以一鼓作氣的完成的定位并顯示了暖释。
1.我們?cè)谥暗腎nitMap方法里加上以下代碼:
// 開啟定位圖層
baiduMap.setMyLocationEnabled(true);
//聲明LocationClient類
mLocationClient = new LocationClient(this);
//注冊(cè)監(jiān)聽函數(shù)
mLocationClient.registerLocationListener(myListener);
initLocation();
//開始定位
mLocationClient.start();
2.聲明一些需要的變量,配置定位參數(shù)墨吓,實(shí)現(xiàn)定位監(jiān)聽方法球匕,設(shè)置中心點(diǎn)和marker
//防止每次定位都重新設(shè)置中心點(diǎn)和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();
//可選帖烘,默認(rèn)高精度亮曹,設(shè)置定位模式,高精度,低功耗照卦,僅設(shè)備
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可選址貌,默認(rèn)gcj02行疏,設(shè)置返回的定位結(jié)果坐標(biāo)系
option.setCoorType("bd09ll");
//可選状知,默認(rèn)0耙箍,即僅定位一次,設(shè)置發(fā)起定位請(qǐng)求的間隔需要大于等于1000ms才是有效的
int span = 5000;
option.setScanSpan(span);
//可選瞬痘,設(shè)置是否需要地址信息故慈,默認(rèn)不需要
option.setIsNeedAddress(true);
//可選,默認(rèn)false,設(shè)置是否使用gps
option.setOpenGps(true);
//可選图云,默認(rèn)false惯悠,設(shè)置是否當(dāng)GPS有效時(shí)按照1S/1次頻率輸出GPS結(jié)果
option.setLocationNotify(true);
//可選邻邮,默認(rèn)false竣况,設(shè)置是否需要位置語(yǔ)義化結(jié)果,可以在BDLocation.getLocationDescribe里得到筒严,結(jié)果類似于“在北京天安門附近”
option.setIsNeedLocationDescribe(true);
//可選丹泉,默認(rèn)false,設(shè)置是否需要POI結(jié)果鸭蛙,可以在BDLocation.getPoiList里得到
option.setIsNeedLocationPoiList(true);
//可選摹恨,默認(rèn)true,定位SDK內(nèi)部是一個(gè)SERVICE娶视,并放到了獨(dú)立進(jìn)程晒哄,設(shè)置是否在stop的時(shí)候殺死這個(gè)進(jìn)程,默認(rèn)不殺死
option.setIgnoreKillProcess(false);
//可選肪获,默認(rèn)false寝凌,設(shè)置是否收集CRASH信息,默認(rèn)收集
option.SetIgnoreCacheException(false);
//可選孝赫,默認(rèn)false较木,設(shè)置是否需要過濾GPS仿真結(jié)果,默認(rèn)需要
option.setEnableSimulateGps(false);
mLocationClient.setLocOption(option);
}
/**
* 實(shí)現(xiàn)定位監(jiān)聽 位置一旦有所改變就會(huì)調(diào)用這個(gè)方法
* 可以在這個(gè)方法里面獲取到定位之后獲取到的一系列數(shù)據(jù)
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//獲取定位結(jié)果
location.getTime(); //獲取定位時(shí)間
location.getLocationID(); //獲取定位唯一ID青柄,v7.2版本新增伐债,用于排查定位問題
location.getLocType(); //獲取定位類型
location.getLatitude(); //獲取緯度信息
location.getLongitude(); //獲取經(jīng)度信息
location.getRadius(); //獲取定位精準(zhǔn)度
location.getAddrStr(); //獲取地址信息
location.getCountry(); //獲取國(guó)家信息
location.getCountryCode(); //獲取國(guó)家碼
location.getCity(); //獲取城市信息
location.getCityCode(); //獲取城市碼
location.getDistrict(); //獲取區(qū)縣信息
location.getStreet(); //獲取街道信息
location.getStreetNumber(); //獲取街道碼
location.getLocationDescribe(); //獲取當(dāng)前位置描述信息
location.getPoiList(); //獲取當(dāng)前位置周邊POI信息
location.getBuildingID(); //室內(nèi)精準(zhǔn)定位下,獲取樓宇I(lǐng)D
location.getBuildingName(); //室內(nèi)精準(zhǔn)定位下致开,獲取樓宇名稱
location.getFloor(); //室內(nèi)精準(zhǔn)定位下峰锁,獲取當(dāng)前位置所處的樓層信息
//經(jīng)緯度
lat = location.getLatitude();
lon = location.getLongitude();
//這個(gè)判斷是為了防止每次定位都重新設(shè)置中心點(diǎn)和marker
if (isFirstLocation) {
isFirstLocation = false;
//設(shè)置并顯示中心點(diǎn)
setPosition2Center(baiduMap, location, true);
}
}
}
/**
* 設(shè)置中心點(diǎn)和添加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.最后我們?cè)趏nCreate方法里進(jìn)行android版本的判斷,根據(jù)android版本來決定直接定位顯示還是需要?jiǎng)討B(tài)權(quán)限以及需要在權(quán)限申請(qǐng)成功的方法里調(diào)用initMap方法和生命周期的管理双戳,代碼如下:
//當(dāng)android系統(tǒng)小于5.0的時(shí)候直接定位顯示祖今,不用動(dòng)態(tài)申請(qǐng)權(quán)限
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
initMap();
} else {
MainActivityPermissionsDispatcher.ApplySuccessWithCheck(this);
}
/**
* 申請(qǐng)權(quán)限成功時(shí)
*/
@NeedsPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
void ApplySuccess() {
initMap();
}
@Override
public void onResume() {
super.onResume();
//在activity執(zhí)行onResume時(shí)執(zhí)行mMapView. onResume (),實(shí)現(xiàn)地圖生命周期管理
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
//在activity執(zhí)行onPause時(shí)執(zhí)行mMapView. onPause (),實(shí)現(xiàn)地圖生命周期管理
mapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
//在activity執(zhí)行onDestroy時(shí)執(zhí)行mMapView.onDestroy()千诬,實(shí)現(xiàn)地圖生命周期管理
// 退出時(shí)銷毀定位
mLocationClient.unRegisterLocationListener(myListener);
mLocationClient.stop();
// 關(guān)閉定位圖層
baiduMap.setMyLocationEnabled(false);
mapView.onDestroy();
mapView = null;
}
最后我們來看看運(yùn)行效果
到此為止耍目,android集成百度地圖的定位與顯示當(dāng)前位置就結(jié)束了,從第一篇文章到第二篇所有的地方我都注釋的比較細(xì)徐绑,以便新手學(xué)習(xí)和參考邪驮。最后因?yàn)槲夜镜捻?xiàng)目中還涉及到了動(dòng)態(tài)添加點(diǎn)和幾何圖形覆蓋物,所以還有有一篇結(jié)尾的文章傲茄,大家耐心等待~