
正文
百度地图sdk定位和遇到的坑
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
封装定位服务类:
import android.content.Context;import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode;/**
*
* @author baidu
*
*/
public class LocationService {
private LocationClient client = null;
private LocationClientOption mOption,DIYoption;
private Object objLock = new Object(); /***
*
* @param locationContext
*/
public LocationService(Context locationContext){
synchronized (objLock) {
if(client == null){
client = new LocationClient(locationContext);
client.setLocOption(getDefaultLocationClientOption());
}
}
} /***
*
* @param listener
* @return
*/ public boolean registerListener(BDAbstractLocationListener listener){
boolean isSuccess = false;
if(listener != null){
client.registerLocationListener(listener);
isSuccess = true;
}
return isSuccess;
} public void unregisterListener(BDAbstractLocationListener listener){
if(listener != null){
client.unRegisterLocationListener(listener);
}
} /***
*
* @param option
* @return isSuccessSetOption
*/
public boolean setLocationOption(LocationClientOption option){
boolean isSuccess = false;
if(option != null){
if(client.isStarted())
client.stop();
DIYoption = option;
client.setLocOption(option);
}
return isSuccess;
} /***
*
* @return DefaultLocationClientOption 默认O设置
*/
public LocationClientOption getDefaultLocationClientOption(){
if(mOption == null){
mOption = new LocationClientOption();
//如果使用设备模式(LocationMode.Device_Sensors),只能在线定位,如果断网,回调方法就不会调用,坑。
//所以只能设置高精度模式
mOption.setLocationMode(LocationMode.Hight_Accuracy);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备 mOption.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系,如果配合百度地图使用,建议设置为bd09ll;
mOption.setScanSpan(5 * 1000);//可选,默认0,即仅定位一次,设置发起连续定位请求的间隔需要大于等于1000ms才是有效的
mOption.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
mOption.setIsNeedLocationDescribe(true);//可选,设置是否需要地址描述
mOption.setNeedDeviceDirect(false);//可选,设置是否需要设备方向结果
mOption.setLocationNotify(false);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果
mOption.setIgnoreKillProcess(true);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
mOption.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
mOption.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
mOption.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集
mOption.setOpenGps(true);//可选,默认false,设置是否开启Gps定位
mOption.setIsNeedAltitude(false);//可选,默认false,设置定位时是否需要海拔信息,默认不需要,除基础定位版本都可用 }
return mOption;
} /**
*
* @return DIYOption 自定义Option设置
*/
public LocationClientOption getOption(){
if(DIYoption == null) {
DIYoption = new LocationClientOption();
}
return DIYoption;
} public void start(){
synchronized (objLock) {
if(client != null && !client.isStarted()){
client.start();
}
}
}
public void stop(){
synchronized (objLock) {
if(client != null && client.isStarted()){
client.stop();
}
}
} public boolean isStart() {
return client.isStarted();
} public boolean requestHotSpotState(){
return client.requestHotSpotState();
}}
全局类中onCreate方法中初始化定位服务:
import com.baidu.mapapi.SDKInitializer;/**
* 全局应用程序类:用于保存用户信息,和全局应用配置及网络请求等服务初始化
*
*/
public class AppContext extends Application { ... ... public LocationService locationService;
public Vibrator mVibrator; /**
* 获得当前app运行的AppContext
*
* @return
*/
public static AppContext getInstance() {
return instance;
} @Override
public void onCreate() {
super.onCreate();
instance = this;
initBaiduSDK();
} private void initBaiduSDK() {
/***
* 初始化定位sdk,建议在Application中创建
*/
locationService = new LocationService(getApplicationContext());
mVibrator = (Vibrator) getApplicationContext().getSystemService(Service.VIBRATOR_SERVICE);
SDKInitializer.initialize(getApplicationContext());
}}
编写一个Service,后台运行
/*
* 运行定时上传当前位置服务
* */
public class UploadLocationService extends Service { //60秒上传一次位置
private static Integer UPLOAD_SECONDS = 20;
//如果位置不变,大于此秒数后,必须上传当前位置,5分钟必须上传一次
private static Integer MAX_UPLOAD_SECONDS = 1 * 60; private LocationService locationService; private static List<PatrolGpsPositionDetailVO> gpsPositionList = new ArrayList<>();
private static Object lockObj = new Object();
//定时器
private Timer timer;
//最后一次的位置信息
private static BDLocation lastLocation = null;
//最后一次上传
private static Date lastUploadDate = null; private static PatrolGpsPositionDetailVO lastGpsPositionVo = null; private static Context context = null; @Override
public void onCreate() {
super.onCreate();
initBaiduMap(); } private void initBaiduMap() { locationService = ((AppContext) getApplication()).locationService; locationService.registerListener(new BDAbstractLocationListener() {
@Override
public void onReceiveLocation(BDLocation location) {
if (null != location) {
writeLocation(location);
}
} @Override
public void onConnectHotSpotMessage(String var1, int var2) {
Log.d("test", "-------onConnectHotSpotMessage----------------------------------------------");
} @Override
public void onLocDiagnosticMessage(int var1, int var2, String var3) {
Log.d("test", "-------onLocDiagnosticMessage----------------------------------------------");
}
}); locationService.start();
} private void writeLocation(BDLocation location) { StringBuffer sb = new StringBuffer(256);
sb.append("time : ");
/**
* 时间也可以使用systemClock.elapsedRealtime()方法 获取的是自从开机以来,每次回调的时间;
* location.getTime() 是指服务端出本次结果的时间,如果位置不发生变化,则时间不变
*/
sb.append(location.getTime());
sb.append("\nlocType : ");// 定位类型
sb.append(location.getLocType());
sb.append("\nlocType description : ");// *****对应的定位类型说明*****
sb.append(location.getLocTypeDescription());
sb.append("\nlatitude : ");// 纬度
sb.append(location.getLatitude());
sb.append("\nlontitude : ");// 经度
sb.append(location.getLongitude());
sb.append("\nradius : ");// 半径
sb.append(location.getRadius());
sb.append("\nCountryCode : ");// 国家码
sb.append(location.getCountryCode());
sb.append("\nCountry : ");// 国家名称
sb.append(location.getCountry());
sb.append("\ncitycode : ");// 城市编码
sb.append(location.getCityCode());
sb.append("\ncity : ");// 城市
sb.append(location.getCity());
sb.append("\nDistrict : ");// 区
sb.append(location.getDistrict());
sb.append("\nStreet : ");// 街道
sb.append(location.getStreet());
sb.append("\naddr : ");// 地址信息
sb.append(location.getAddrStr());
sb.append("\nUserIndoorState: ");// *****返回用户室内外判断结果*****
sb.append(location.getUserIndoorState());
sb.append("\nDirection(not all devices have value): ");
sb.append(location.getDirection());// 方向
sb.append("\nlocationdescribe: ");
sb.append(location.getLocationDescribe());// 位置语义化信息
sb.append("\nPoi: ");// POI信息
if (location.getPoiList() != null && !location.getPoiList().isEmpty()) {
for (int i = 0; i < location.getPoiList().size(); i++) {
Poi poi = (Poi) location.getPoiList().get(i);
sb.append(poi.getName() + ";");
}
}
if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果
sb.append("\nspeed : ");
sb.append(location.getSpeed());// 速度 单位:km/h
sb.append("\nsatellite : ");
sb.append(location.getSatelliteNumber());// 卫星数目
sb.append("\nheight : ");
sb.append(location.getAltitude());// 海拔高度 单位:米
sb.append("\ngps status : ");
sb.append(location.getGpsAccuracyStatus());// *****gps质量判断*****
sb.append("\ndescribe : ");
sb.append("gps定位成功");
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果
// 运营商信息
if (location.hasAltitude()) {// *****如果有海拔高度*****
sb.append("\nheight : ");
sb.append(location.getAltitude());// 单位:米
}
sb.append("\noperationers : ");// 运营商信息
sb.append(location.getOperators());
sb.append("\ndescribe : ");
sb.append("网络定位成功");
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果
sb.append("\ndescribe : ");
sb.append("离线定位成功,离线定位结果也是有效的");
} else if (location.getLocType() == BDLocation.TypeServerError) {
sb.append("\ndescribe : ");
sb.append("服务端网络定位失败,可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com,会有人追查原因");
} else if (location.getLocType() == BDLocation.TypeNetWorkException) {
sb.append("\ndescribe : ");
sb.append("网络不同导致定位失败,请检查网络是否通畅");
} else if (location.getLocType() == BDLocation.TypeCriteriaException) {
sb.append("\ndescribe : ");
sb.append("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机");
}
Log.d("location", sb.toString());
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("test", "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
Log.e("test","service ondestory");
locationService.stop();
stopForeground(true);// 停止前台服务--参数:表示是否移除之前的通知
super.onDestroy();
}}
启动或者关闭服务方法,可以在需要时调用,写法如下:
public static void controlLocationService(Context context, Boolean isStart) {
Intent intent = new Intent(context, UploadLocationService.class);
if (isStart) {
context.startService(intent);
} else {
context.stopService(intent);
}
}
百度地图和百度定位sdk的坑
1.百度地图zoom大小和对应的长度米的单位如下,zoom为15时,对应的是200米,不是对应500米,要改小,改成14.8才对应500米
public enum BaiduMapZoom { //"10m", "20m", "50m", "100m", "200m",
//"500m", "1km", "2km", "5km", "10km",
//"20km", "25km", "50km", "100km", "200km"
//"500km", "1000km", "2000km"
zoom_20(20,10),
zoom_19(19,20),
zoom_18(18,50),
zoom_17(17,100),
zoom_16(16,200), zoom_15(14.8F,500),
zoom_14(14,1000),
zoom_13(13,2000),
zoom_12(12,5000),
zoom_11(11,10000), zoom_10(10,20000),
zoom_9(9,25000),
zoom_8(8,50000),
zoom_7(7,100000),
; private float zoom; private int unitDistance; BaiduMapZoom(float zoom,int unitDistance){
this.zoom = zoom;
this.unitDistance = unitDistance;
} public float getZoom() {
return zoom;
} public void setZoom(int zoom) {
this.zoom = zoom;
} public int getUnitDistance() {
return unitDistance;
} public void setUnitDistance(int unitDistance) {
this.unitDistance = unitDistance;
}}
2.地图SDK定位中定位模式有3种,高精度,低功耗,仅设备
建议使用高精度模式,仅设备模式下无法离线定位,出现回调函数不调用的问题。高精度模式下没有此问题,可以离线定位。
mOption.setLocationMode(LocationMode.Hight_Accuracy); //高精度模式








