定位功能在app开发中很常用,大多数企业都是不具备定位资质的,所有一般是通过接入第三方的sdk来进行定位,比较熟悉的有如:百度、高德、谷歌、腾讯等。而国内比较地图策划比较成熟的主要是百度和高德,这里就以百度为例,介绍一下接入流程和方法。
详细资料请查看官方SDK文档:
http://developer.baidu.com/map/index.php?title=android-locsdk/guide/v5-0
这里是官方实例代码和SDK下载地址:
BaiduLBS_AndroidSDK_Sample.zip
使用百度定位SDK必须去官网注册开发者账号并申请key:
http://developer.baidu.com/map/index.php?title=android-locsdk/guide/key
官方文档把接入方法写的很详细,推荐直接看文档,下面我总结一下接入的流程和遇到的问题:
首先要做的是导入库文件:
下载SDK把SDK中的.so文件及其目录和locSDK_xxx.jar都导入进工程的libs目录下
百度的定位功能和地图功能是分开的,所以只需要引入定位的相关类库就可以了,如下:
不同的目录下都导入了相应的liblocSDK.so是为了兼容执行不同指令集的CPU的机型,这里不需要理解,直接拷贝下去就可以了。
然后设置AndroidManifest.xml文件并添加相应权限:
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 这个权限用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!-- 用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD卡读取权限,用户写入离线定位数据-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
百度的定位在Service中完成处理的,所以要现在AndroidManifest.xml声明这个Service
在<application>
节点下添加一个用于定位的后台Service的声明:
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote">
</service>
使用百度定位SDK必须去官网注册开发者账号并申请key,把申请到的key填入AndroidManifest.xml文件中
在<application>
节点下添加key常量:
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="key" /> //key:开发者申请的key
配置完成了,下面就可以初始化了:
mLocationClient = new LocationClient(this.getApplicationContext());
由于定位功能在app中的各个页面可能都会用到,所以建议把上面的mLocationClient 初始化放在Application中作为全局变量来使用,当然你也可以在每个Activity中都去new一个,但是不建议这样做。
具体设置方法:
新建一个类继承自Application,定义一个公用的LocationClient 并在onCreate中实例化:
public class MyApplication extends Application { public LocationClient mLocationClient; @Override public void onCreate() { super.onCreate(); //baidu loc mLocationClient = new LocationClient(this.getApplicationContext()); } }
然后在自己的Activity中取得这个LocationClient,并设置定位监听:
mLocationClient = ((MyApplication)getApplication()).mLocationClient; mLocationClient.registerLocationListener(new MyLocationListener());
监听器代码示例如下,这里只打印城市展示:
public class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { //打印出当前的城市名 Toast.makeText(this, location.getCity(), Toast.LENGTH_SHORT).show(); //location.getLongitude(); 获取当前位置经度 //location.getLatitude(); 获取当前位置纬度 } }
值得注意的是:mLocationClient 是属于Application的全局变量,我们给他注册了一个在本地Activity中声明的定位监听器MyLocationListener,由于Application的生命周期比Activity长,所以在关闭这个页面的时候,mLocationClient 任然持有这个监听对象的引用就会导致该Activity无法释放从而导致内存泄露,虽然运行之后看不出来,但是一旦你重复多次打开关闭定位页面就会发现,app所占用的内存会不断递增直到爆炸应用崩溃。所有还应该做一件事,就是在该页面关闭的时候及时注销这个监听器:
务必在Activity的onDestroy方法中添加如下代码:
@Override protected void onDestroy() { mLocationClient.unRegisterLocationListener(this);//取消注册的位置监听,以免内存泄露 mLocationClient.stop();// 退出时销毁定位 super.onDestroy(); }
到这里,我们初始化了定位类并注册了设置监听,下面我们给定位类设置相应参数后就可以启动定位了:
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll"); // 设置坐标类型
option.setIsNeedAddress(true); //设置是否需要地址信息,默认不需要
//option.setScanSpan(1000); //多久定位一次
mLocationClient.setLocOption(option);
注意要获取当前城市必须设option.setIsNeedAddress(true)
,否则默认为false,获取城市会返回null
option.setScanSpan(1000)
表示多久定位一次,0表示只定义一次,默认设置是0,重复定位会加快手机耗电并且影响性能,如果没有实时定位的需要的话,不要设置该属性。
设置完参数后,就可以开始定位了:
mLocationClient.start();
这里功能就集成完毕了,只需要自定义你的定位监听器MyLocationListener 重写其onReceiveLocation(location)方法来执行你自己的逻辑就ok了。
location.getCity(); //获取当前城市名
location.getLongitude(); //获取当前位置经度
location.getLatitude(); //获取当前位置纬度
这里贴出了获取当前城市名和经纬度的方法,其他的请参考官方帮助文档:
http://wiki.lbsyun.baidu.com/cms/androidloc/doc/v6_0_3/doc/index.html