上一讲我们介绍了如何在Activity中显示百度地图,很多情况下我们都需要在百度地图上显示当前位置。百度地图Android SDK更新到2.0之后,将定位功能进行了剥离,但它依旧保留了定位图层,方便开发者便捷的展示定位结果等信息。所以获取当前位置需要结合百度定位SDK使用。
1、添加定位sdk
所先在官方相关下载中下载最新的库文件。然后将liblocSDK3.so文件拷贝到libs/armeabi目录下。将locSDK3.3.jar文件拷贝到工程的libs目录下,并在工程属性->Java Build Path->Libraries中选择“Add JARs”,选定locSDK3.3.jar,确定后返回。现在我们工程的libs目录应该是这个样子:
2、设置AndroidManifest.xml
在application标签中声明service组件。
12 | <service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"></service> |
并声明使用权限
1234567 | <!-- 使用定位功能所需权限 --><uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/><permissionandroid:name="android.permission.BAIDU_LOCATION_SERVICE"/><uses-permissionandroid:name="android.permission.BAIDU_LOCATION_SERVICE"/><uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permissionandroid:name="android.permission.ACCES_MOCK_LOCATION"/><uses-permissionandroid:name="android.permission.ACCESS_GPS"/> |
3、新建相关Activity关实现代码
新建一个类ShowMyLocationActivity继承至Activity,并在AndroidManifest.xml注册。相关代码如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 | package com.liuzhichao.baidumapdemo; import android.app.Activity;import android.os.Bundle;import android.widget.Toast; import com.baidu.location.BDLocation;import com.baidu.location.BDLocationListener;import com.baidu.location.LocationClient;import com.baidu.location.LocationClientOption;import com.baidu.mapapi.map.LocationData;import com.baidu.mapapi.map.MapController;import com.baidu.mapapi.map.MapView;import com.baidu.mapapi.map.MyLocationOverlay;import com.baidu.platform.comapi.basestruct.GeoPoint; /** * 在百度地图上显示当前位置 * @author liuzc * @url http://liuzhichao.com * @mail liuzc89@gmail.com */public class ShowMyLocationActivity extends Activity{ private LocationClient mLocationClient; private BDLocationListener myListener; private MapView mMapView; private MapController mMapController = null; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_map); //初始化百度地图 initMapView(); //初始化LocationClient类,推荐用getApplicationConext获取全进程有效的context mLocationClient = new LocationClient(getApplicationContext()); //定位相关设置 setLocOption(mLocationClient); //定位回调函数 myListener = new MyLocationListenner(); //注册监听函数 mLocationClient.registerLocationListener(myListener); //开启定位 mLocationClient.start(); System.out.println("start----mLocationClient.isStarted:"+mLocationClient.isStarted()); } //初始化百度地图 private void initMapView() { mMapView = (MapView) findViewById(R.id.bmapsView); mMapController = mMapView.getController(); mMapController.setZoom(14); } //设置定位参数包括:定位模式(单次定位,定时定位),返回坐标类型,是否打开GPS等等 private void setLocOption(LocationClient mLocClient){ LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); //是否打开gps option.setAddrType("all");//设置是否要返回地址信息,String 值为 all时,表示返回地址信息。其他值都表示不返回地址信息。 option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02 //当所设的整数值大于等于1000(ms)时,定位SDK内部使用定时定位模式。调用requestLocation( )后,每隔设定的时间,定位SDK就会进行一次定位。 //当不设此项,或者所设的整数值小于1000(ms)时,采用一次定位模式。 option.setScanSpan(1000);//设置发起定位请求的间隔时间为5000ms option.disableCache(true);//true表示禁用缓存定位,false表示启用缓存定位。 option.setPoiNumber(5); //最多返回POI个数 option.setPoiDistance(1000); //poi查询距离 option.setPoiExtraInfo(true); //是否需要POI的电话和地址等详细信息 mLocClient.setLocOption(option); } public class MyLocationListenner implements BDLocationListener{ @Override public void onReceiveLocation(BDLocation location) { if (location==null) { Toast.makeText(getApplicationContext(), "获取位置信息失败", Toast.LENGTH_LONG).show(); return; } Toast.makeText(getApplicationContext(), "定位成功:"+location.getAddrStr(), Toast.LENGTH_LONG).show(); showMyLocationOnMap(location.getLatitude(), location.getLongitude()); } @Override public void onReceivePoi(BDLocation location) { } } /** * 根据传入的经纬度在地图上显示 * @param latitude * @param longitude */ private void showMyLocationOnMap(double latitude,double longitude){ MyLocationOverlay myLocationOverlay = new MyLocationOverlay(mMapView); LocationData locData = new LocationData(); locData.latitude = latitude; locData.longitude = longitude; locData.direction = 2.0f; myLocationOverlay.setData(locData); mMapView.getOverlays().add(myLocationOverlay); mMapView.refresh(); mMapController.animateTo(new GeoPoint((int)(locData.latitude*1e6),(int)(locData.longitude* 1e6))); //定位成功后关闭定位 mLocationClient.stop(); //取消监听函数。 mLocationClient.unRegisterLocationListener(myListener); System.out.println("stop----mLocationClient.isStarted:"+mLocationClient.isStarted()); } } |
4、在MainActivity中添加到该类的”导航”:
1234567891011121314151617181920212223242526272829303132333435 | publicclassMainActivityextendsListActivity{ privateContextcontext; privateString[]demos={"1、显示百度地图","2、在百度地图上显示当前位置"}; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); context=this; setListAdapter(newArrayAdapter<String>(this,android.R.layout.simple_list_item_1,demos)); getListView().setOnItemClickListener(newOnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>parent,Viewview, intposition,longid){ Intentintent=null; switch(position){ case0: intent=newIntent(context,ShowMapActivity.class); break; case1: intent=newIntent(context,ShowMyLocationActivity.class); break; default: break; } if(intent!=null){ startActivity(intent); } } }); }} |
运行程序并点击“在百度地图上显示当前位置”,运行结果如下:
可以看出已经在地图上正确的显示了当前位置,但是存在一些比较怪异的地方:
1、我们并没有发送定位请求(并没有调用mLocationClient.requestLocation(或mLocationClient.requestPoi())就开始了定位。
2、仔细观察代码中两处关于mLocationClient.isStarted的打印信息,我们发现在调用mLocationClient.start()后,mLocationClient.isStarted返回的是false,而在调用mLocationClient.stop()后,mLocationClient.isStarted返回的反而是true;
所以下面的代码反而是错误的:
12345 | if (mLocationClient!=null && mLocationClient.isStarted()) { mLocationClient.requestLocation(); }else{ Toast.makeText(this, "定位失败", Toast.LENGTH_LONG).show(); } |
你会发现mLocationClient.requestLocation()并不会执行,而是显示”定位失败”。这时如果你没有调用mLocationClient.start(),则不能正常定位。所以我在想,是不是在调用mLocationClient.start()的时候,就开始定位了?但是这样的话,mLocationClient.requestLocation()或mLocationClient.requestPoi(),还有离线定位mLocationClient.requestOfflineLocation(),还有什么意义呢?
不过我们仍然是可以区分的,因为调用mLocationClient.requestPoi()的时候,返回的结果是在回调接口中的onReceivePoi()中处理。调用离线定位mLocationClient.requestOfflineLocation()时,返回结果虽然也是在回调接口中的onReceiveLocation()中,我们可以使用如下方法判断是否是离线定位请求:
123456789101112 | @Override publicvoidonReceiveLocation(BDLocationlocation){ if(location==null){ Toast.makeText(getApplicationContext(),"获取位置信息失败",Toast.LENGTH_LONG).show(); return; } if(location.getLocType()==BDLocation.TypeOffLineLocation){ //离线定位请求返回的定位结果 } } |
原文地址:点击打开链接