这是当前项目的第二个需求,返回当前的位置
这个需求在百度地图里面实现很简单,但是出了一大堆的乱起八糟的错误,错误等到后面的文章再说,先说要获取当前位置怎么做
原理很简单:
第一个需要是的通过 GPS返回geocode
第二步就是反geo转码得到地址输出来就可以了
实现的时候就三个东西:
1.定位器 百度里面称为 LocationClient
2.返回结果的监听器 百度里面是 一个接口类 BDLocationListener 我们需要去实现他就可以了
3.结果的反编译 因为返回的结果是经纬度 百度里面是 GeoCoder
只需要用到这三个东西就可以实现获取当前的位置,首先我们看看怎么使用百度提供的demo来搞定 我把多余的代码全部去掉了
/** * 此demo用来展示如何结合定位SDK实现定位,并使用MyLocationOverlay绘制定位位置 同时展示如何使用自定义图标绘制并点击时弹出泡泡 * */ public class LocationDemo extends Activity implements OnGetGeoCoderResultListener { // 定位相关 LocationClient mLocClient; public MyLocationListenner myListener = new MyLocationListenner(); GeoCoder mSearch = null;//反编译地理位置 private String locationStrAddress;//这个变量就是存储 汉字地址 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_location); // 定位初始化 mLocClient = new LocationClient(this);//在百度里面 这里的参数是this 他在全局变量application里面已经初始化地图了,
//但是我觉得还是需要改成getapplicationContext()为好 mLocClient.registerLocationListener(myListener); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true);// 打开gps option.setCoorType("bd09ll"); // 设置坐标类型 这个好像是百度的经纬度类型,还有国测局加密经纬度gcj02 还有bd09 是百度加密墨卡托坐标 option.setScanSpan(1000); mLocClient.setLocOption(option); mLocClient.start(); // 初始化搜索模块,注册事件监听 mSearch = GeoCoder.newInstance(); mSearch.setOnGetGeoCodeResultListener(this); } /** * 定位SDK监听函数 */ public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { // map view 销毁后不在处理新接收的位置 if (location == null) return; LatLng ll = new LatLng(location.getLatitude(),location.getLongitude()); mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(ll));//这个位置就是反编译处理 } public void onReceivePoi(BDLocation poiLocation) { } } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { // 退出时销毁定位 mLocClient.stop(); super.onDestroy(); } @Override public void onGetGeoCodeResult(GeoCodeResult result) { //这个是通过汉字转换为经纬度的 } @Override public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) { // TODO Auto-generated method stub if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(LocationDemo.this, "抱歉,未能找到结果", Toast.LENGTH_LONG).show(); locationStrAddress = "抱歉,未能找到结果"; return; } locationStrAddress = result.getAddress().toString(); Toast.makeText(LocationDemo.this, result.getAddress(),Toast.LENGTH_LONG).show(); } }
整个实现就只有上面的那些东西,然后那个类里面要用,直接copy到onCreate里面,重载函数贴进去就ok了,
这个是百度提供的demo方法
接下来看看,在需要调用定位的时候更简单的操作呢,那就是把定位的操作放在application里面,在自己定义的application里面加上下面的代码就可以:
这是变量:
public LocationClient mLocationClient;//定位客户端 public MyLocationListener mMyLocationListener;//监听器
public TextView mLocationResult,logMsg;//这是返回的结果,当前你也可以用String 来存储了
onCreate()里面加上这些代码:
mLocationClient = new LocationClient(this.getApplicationContext()); mMyLocationListener = new MyLocationListener(); mLocationClient.registerLocationListener(mMyLocationListener);
下面是自定义的监听器:
/** * 实现实时位置回调监听 */ public class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { //Receive Location StringBuffer sb = new StringBuffer(256); sb.append("time : "); sb.append(location.getTime()); sb.append("\nerror code : "); sb.append(location.getLocType()); sb.append("\nlatitude : "); sb.append(location.getLatitude()); sb.append("\nlontitude : "); sb.append(location.getLongitude()); sb.append("\nradius : "); sb.append(location.getRadius()); if (location.getLocType() == BDLocation.TypeGpsLocation){// GPS定位结果 sb.append("\nspeed : "); sb.append(location.getSpeed());// 单位:公里每小时 sb.append("\nsatellite : "); sb.append(location.getSatelliteNumber()); sb.append("\nheight : "); sb.append(location.getAltitude());// 单位:米 sb.append("\ndirection : "); sb.append(location.getDirection()); sb.append("\naddr : "); sb.append(location.getAddrStr()); sb.append("\ndescribe : "); sb.append("gps定位成功"); } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){// 网络定位结果 sb.append("\naddr : "); sb.append(location.getCity()); //运营商信息 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("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机"); } logMsg(sb.toString()); Log.i("BaiduLocationApiDem", sb.toString()); // mLocationClient.setEnableGpsRealTimeTransfer(true); } } /** * 显示请求字符串 * @param str */ public void logMsg(String str) { try { if (mLocationResult != null) mLocationResult.setText(str); } catch (Exception e) { e.printStackTrace(); } }
在application里面完成上面的操作之后,每次需要调用定位的时候就这样做,比如在一个activity里面:
变量定义:
private LocationClient mLocationClient; private TextView LocationResult;
onCreate()里面初始化:
mLocationClient = ((LocationApplication)getApplication()).mLocationClient;
((LocationApplication)getApplication()).mLocationResult = LocationResult;//这个时候他的结果是没有值的,因为还没有启动定位
接下来就是启动定位了:
private void initLocation(){ LocationClientOption option = new LocationClientOption(); option.setLocationMode(tempMode);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备 option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系, int span=1000; try { span = Integer.valueOf(frequence.getText().toString()); } catch (Exception e) { // TODO: handle exception } option.setScanSpan(span);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的 option.setIsNeedAddress(checkGeoLocation.isChecked());//可选,设置是否需要地址信息,默认不需要 option.setOpenGps(true);//可选,默认false,设置是否使用gps option.setLocationNotify(true);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果 option.setIgnoreKillProcess(true);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死 mLocationClient.setLocOption(option); }
那么使用的时候你只需要调用上面的启动函数就行了,不管你是在onCreate里面启动,还是按钮触发事件启动 下面三行代码就可以:
initLocation();//这行代码有时候是多余的,看你在哪里用
mLocationClient.start();//定位SDK start之后会默认发起一次定位请求,开发者无须判断isstart并主动调用request mLocationClient.requestLocation();
这样写有一个好处就是我的 定位客户端初始化再也不关心 context的问题了
但是 使用百度地图定位还是出现很多乱起八糟的问题,很考验人的,接下来看看出现的那些位置吧