百度地图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); //高精度模式