入门新手,记于此以为笔记。代码几乎与百度示例一致,仅增加了一个地图缩放处理,并说明了isStarted的null检查问题。定位效果图如下:
使用 baidumapapi_v3_0_0.jar 和 locSDK_4.1.jar 进行地图定位。布局比较简单,直接使用了一个百度地图的MapView组件,布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <com.baidu.mapapi.map.MapView
- android:id="@+id/bmapView"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:clickable="true" />
- </LinearLayout>
使用百度定位和百度地图都需要一些权限,其中有些是重复的,分别列出如下:
百度定位所需权限:
- <!-- 这个权限用于进行网络定位 -->
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <!-- 这个权限用于访问GPS定位 -->
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <!-- 用于读取手机当前的状态 -->
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据 -->
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <!-- 访问网络,网络定位需要上网 -->
- <uses-permission android:name="android.permission.INTERNET" />
- <!-- SD卡读取权限,用户写入离线定位数据 -->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <!-- 允许应用读取低级别的系统日志文件 -->
- <uses-permission android:name="android.permission.READ_LOGS" />
使用百度地图所需权限:
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- <uses-permission android:name="android.permission.USE_CREDENTIALS" />
- <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
- <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.BROADCAST_STICKY" />
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
新版本的百度地图使用时还需要一个KEY密钥,这可以免费申请,然后需要在 AndroidManifest.xml文件中的Application标签中加入Key配置:
- <meta-data
- android:name="com.baidu.lbsapi.API_KEY"
- android:value="你申请的Key密钥" />
对应定位来说,还需要在Application标签中配置一个service属性:
- <service
- android:name="com.baidu.location.f"
- android:enabled="true"
- android:process=":remote" />
在使用SDK的各组件之前需调用SDKInitializer类的静态初始化函数进行全局初始化,这里在OnCreate的setContentView之前调用,因为布局中用到了MapView组件。
MapView组件有三个控制函数:onDestroy()、onPause()、onResume() 用于使销毁、暂停和唤醒百度地图,需要在Activity的相应的函数中调用它们,以更好地管理地图的生命周期。
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //在使用SDK各组件之前初始化context信息,传入ApplicationContext
- //注意该方法要再setContentView方法之前实现
- SDKInitializer.initialize(getApplicationContext());
- setContentView(R.layout.activity_main);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- <span style="white-space:pre"> </span>// 如果开启了定位层的显示,则在销毁前关闭它
- <span style="white-space:pre"> mBaiduMap.setMyLocationEnabled(false); </span>
- // 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
- mMapView.onDestroy();
- }
- @Override
- protected void onResume() {
- super.onResume();
- // 在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
- mMapView.onResume();
- }
- @Override
- protected void onPause() {
- super.onPause();
- // 在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
- mMapView.onPause();
- }
在定位显示时,需要开启地图的定位图层,可通过地图控制器的 setMyLocationEnabled 方法来设置,地图的控制器对象BaiduMap 可由 MapView 的 getMap() 方法获取。需注意的是,在上面的 onDestroy()方法中,进行了定位层关闭的设置,否则,在后面的实时显示定位信息的showLocation函数中的 BaiduMap对象的 setMyLocationData方法调用会出现错误。
进行定位需要一个 LocationClient 对象,然后用该对象的 registerLocationListener 方法注册一个监听器、设置定位选项,并开启定位。
- // 获取地图组件引用及地图控制器
- mMapView = (MapView) findViewById(R.id.bmapView);
- mBaiduMap = mMapView.getMap();
- // 开启定位图层
- mBaiduMap.setMyLocationEnabled(true);
- mLocationClient = new LocationClient(getApplicationContext()); // 声明LocationClient类
- mLocationClient.registerLocationListener(myListener); // 注册监听器
- // 设置定位选项
- LocationClientOption option = new LocationClientOption();
- // option.disableCache(true); // 是否允许缓存
- option.setLocationMode(LocationMode.Hight_Accuracy);// 设置定位模式
- option.setOpenGps(true); // 开启GPS
- option.setCoorType("bd09ll");// 返回的定位结果是百度经纬度,默认值gcj02
- option.setScanSpan(2000);// 设置发起定位请求的间隔时间为2000ms
- option.setIsNeedAddress(true);// 返回的定位结果包含地址信息
- option.setNeedDeviceDirect(true);// 返回的定位结果包含手机机头的方向
- mLocationClient.setLocOption(option);
- mLocationClient.start(); // 启动定位
其中 myListener 的声明为:
- BDLocationListener myListener = new MyLocationListener();
- public class MyLocationListener implements BDLocationListener {
- @Override
- public void onReceiveLocation(BDLocation location) {
- if (location == null)
- return;
- showLocation(location);
- }
- public void onReceivePoi(BDLocation poiLocation) {
- // 将在下个版本中去除poi功能
- if (poiLocation == null) {
- return;
- }
- }
- }
在showLocation 函数中进行数据数据处理,然后在地图中标出当前位置:
- public void showLocation(BDLocation location) {
- // 构造定位数据
- MyLocationData locData = new MyLocationData.Builder()
- .accuracy(location.getRadius())
- // 此处设置开发者获取到的方向信息,顺时针0-360
- .direction(location.getDirection()).latitude(location.getLatitude())
- .longitude(location.getLongitude()).build();
- // 设置定位数据
- mBaiduMap.setMyLocationData(locData);
- // 缩放设置
- if (isFirstLoc) {
- isFirstLoc = false;
- // 设置地图缩放比例:17级100米
- MapStatusUpdate ms = MapStatusUpdateFactory.zoomTo(17);
- mBaiduMap.setMapStatus(ms);
- }
- // 更新地图位置
- LatLng ll = new LatLng(location.getLatitude(),
- location.getLongitude());
- MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
- mBaiduMap.animateMapStatus(u);
- }
仅在第一次定位后设置地图的显示比例,将其放大到100米级别。最后的“更新地图位置”部分放到了if 条件之外,这样在每次定位后或在地图移到其它地方后,都会将新的定位后的位置显示在屏幕中。
实际上定位层的显示有一个相应的模式,默认的模式为 NORMAL,这种模式下地图不会根据定位信息进行更新,因此在本例中使用了手动更新方式,即取得经纬度后用animateMapStatus 方法来改变地图的状态,以达到实时更新定位层的目的。在(二)中将说明定位层的显示方式。
在百度定位开发的介绍示例中有一个定位端启动的判断:
- mLocationClient.setLocOption(option);
- mLocationClient.start();
- if (mLocationClient != null && mLocationClient.isStarted())
- mLocationClient.requestLocation();
- else
- Log.d("LocSDK4", "locationClient is null or not started");
这仅是在启动后手动地调用一个定位请求,但这是可省略的。实际上 isStarted函数的返回几乎都为 null ,但这并不影响后续的定位,因为启动需要时间,而此处的检查显然是太紧急了的。根据论坛里说是因为这些示例更新尚未完善,因此不必纠结于此处的 null 问题。
另外,所声明的变量有:
- MapView mMapView = null;
- BaiduMap mBaiduMap = null;
- public LocationClient mLocationClient = null;
- public BDLocationListener myListener = new MyLocationListener();
- Boolean isFirstLoc = true;
记录完毕。