这是当前项目的第二个需求,返回当前的位置
这个需求在百度地图里面实现很简单,但是出了一大堆的乱起八糟的错误,错误等到后面的文章再说,先说要获取当前位置怎么做
原理很简单:
第一个需要是的通过 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号和大体定位时间到[email protected],会有人追查原因");
} 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的问题了
但是 使用百度地图定位还是出现很多乱起八糟的问题,很考验人的,接下来看看出现的那些位置吧