因为毕设要做到对当前位置实时定位,并计算距离附近的自动售货机的实时位置,因为主要是在大陆地区,所以研究了Android 百度定位SDK
定位SDK会根据设备当前的实际情况(如是否开启GPS,是否连接网络,是否扫描到Wi-Fi信息等)生成定位依据,并根据开发者设置的实际定位策略(包括三种:高精度模式,低功耗模式,仅用设备模式)进行定位。
NOTICE: 百度现在把地图SDK和定位SDK分开,如只需要实现定位功能,不需要使用地图SDK
关于百度SDK更详细的定位原理可以参考百度的文档:http://developer.baidu.com/map/geosdk.htm
步骤:
- 注册百度账号成为开发者后,去http://developer.baidu.com/map/geosdk.htm页面,左下角“相关下载”下载版本,本文采用Android定位SDKv4.1(这里吐槽一句,新版本还存在很多问题,官方提供的demo也有很多bug,程序无法定位,一直显示error code:602)
- 点击获取秘钥,根据网页提示获取属于你当前应用的访问应用(ak)
- 在下载的库文件中,将liblocSDK4.so文件拷贝到libs/armeabi目录下。将locSDK4.1.jar文件拷贝到工程的libs目录下,并在工程属性->Java Build Path->Libraries中选择“Add JARs”,选定locSDK4.1.jar,确定后返回。这样您就可以在程序中使用百度地理围栏SDK了。
- 设置AndroidManifest.xml
- 在Application标签中声明service组件,每个app拥有自己单独的定位service
1
2
3
4
5
6
7
8
9
|
<service
android
:
name
=
"com.baidu.location.f"
android
:
enabled
=
"true"
android
:
process
=
":remote"
>
</service>
<meta-data
android
:
name
=
"com.baidu.lbsapi.API_KEY"
android
:
value
=
"填写访问应用(ak)"
/>
|
- 声明使用权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<!-- 这个权限用于进行网络定位 -->
<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>
<!-- 允许应用读取低级别的系统日志文件 -->
<uses-permission android
:
name
=
"android.permission.READ_LOGS"
>
</uses-permission>
|
配置完后,既可以在MainActivity.java中写代码,代码如下:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
package
com
.
example
.
baidudistancedemo
;
import
android
.
app
.
Activity
;
import
android
.
os
.
Bundle
;
import
android
.
util
.
Log
;
import
android
.
view
.
View
;
import
android
.
view
.
View
.
OnClickListener
;
import
android
.
widget
.
Button
;
import
android
.
widget
.
TextView
;
import
com
.
baidu
.
location
.
BDLocation
;
import
com
.
baidu
.
location
.
BDLocationListener
;
import
com
.
baidu
.
location
.
LocationClient
;
import
com
.
baidu
.
location
.
LocationClientOption
;
/**
* 百度基站定位错误返回码
*/
// 61 : GPS定位结果
// 62 : 扫描整合定位依据失败。此时定位结果无效。
// 63 : 网络异常,没有成功向服务器发起请求。此时定位结果无效。
// 65 : 定位缓存的结果。
// 66 : 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果
// 67 : 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果
// 68 : 网络连接失败时,查找本地离线定位时对应的返回结果
// 161: 表示网络定位结果
// 162~167: 服务端定位失败
// 502:KEY参数错误
// 505:KEY不存在或者非法
// 601:KEY服务被开发者自己禁用
// 602: KEY Mcode不匹配,意思就是您的ak配置过程中安全码设置有问题,请确保: sha1正确,“;”分号是英文状态;且包名是您当前运行应用的包名
// 501-700:KEY验证失败
public
class
MainActivity
extends
Activity
implements
OnClickListener
{
public
LocationClient
mLocationClient
=
null
;
public
BDLocationListener
myListener
=
new
MyLocationListener
(
)
;
private
static
final
String
TAG
=
"MainActivity"
;
private
TextView
mText
,
mTextPoi
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
setContentView
(
R
.
layout
.
activity_main
)
;
mLocationClient
=
new
LocationClient
(
getApplicationContext
(
)
)
;
// 声明LocationClient类
mLocationClient
.
setAccessKey
(
"uof5MdWhsBtieU4OvMhXQGTm"
)
;
mLocationClient
.
registerLocationListener
(
myListener
)
;
// 注册监听函数
setLocationOption
(
)
;
mLocationClient
.
start
(
)
;
// 开始定位
initWidgets
(
)
;
}
@Override
protected
void
onDestroy
(
)
{
// TODO Auto-generated method stub
super
.
onDestroy
(
)
;
mLocationClient
.
stop
(
)
;
// 停止定位
}
private
void
initWidgets
(
)
{
mText
=
(
TextView
)
findViewById
(
R
.
id
.
tv_text
)
;
mTextPoi
=
(
TextView
)
findViewById
(
R
.
id
.
tv_text_poi
)
;
Button
btn
=
(
Button
)
findViewById
(
R
.
id
.
btn_request
)
;
btn
.
setOnClickListener
(
this
)
;
btn
=
(
Button
)
findViewById
(
R
.
id
.
btn_request_poi
)
;
btn
.
setOnClickListener
(
this
)
;
}
/**
* 设置相关参数
*/
private
void
setLocationOption
(
)
{
LocationClientOption
option
=
new
LocationClientOption
(
)
;
option
.
setOpenGps
(
true
)
;
option
.
setIsNeedAddress
(
true
)
;
// 返回的定位结果包含地址信息
option
.
setAddrType
(
"all"
)
;
// 返回的定位结果包含地址信息
option
.
setCoorType
(
"bd09ll"
)
;
// 返回的定位结果是百度经纬度,默认值gcj02
option
.
setScanSpan
(
5000
)
;
// 设置发起定位请求的间隔时间为5000ms
option
.
disableCache
(
true
)
;
// 禁止启用缓存定位
option
.
setPoiNumber
(
5
)
;
// 最多返回POI个数
option
.
setPoiDistance
(
1000
)
;
// poi查询距离
option
.
setPoiExtraInfo
(
true
)
;
// 是否需要POI的电话和地址等详细信息
mLocationClient
.
setLocOption
(
option
)
;
}
public
class
MyLocationListener
implements
BDLocationListener
{
@Override
public
void
onReceiveLocation
(
BDLocation
location
)
{
if
(
location
==
null
)
return
;
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
)
{
sb
.
append
(
"\nspeed : "
)
;
sb
.
append
(
location
.
getSpeed
(
)
)
;
sb
.
append
(
"\nsatellite : "
)
;
sb
.
append
(
location
.
getSatelliteNumber
(
)
)
;
}
else
if
(
location
.
getLocType
(
)
==
BDLocation
.
TypeNetWorkLocation
)
{
sb
.
append
(
"\naddr : "
)
;
sb
.
append
(
location
.
getAddrStr
(
)
)
;
}
mText
.
setText
(
sb
.
toString
(
)
)
;
Log
.
d
(
TAG
,
"onReceiveLocation "
+
sb
.
toString
(
)
)
;
}
public
void
onReceivePoi
(
BDLocation
poiLocation
)
{
// 将在下个版本中去除poi功能
if
(
poiLocation
==
null
)
{
return
;
}
StringBuffer
sb
=
new
StringBuffer
(
256
)
;
sb
.
append
(
"Poi time : "
)
;
sb
.
append
(
poiLocation
.
getTime
(
)
)
;
sb
.
append
(
"\nerror code : "
)
;
sb
.
append
(
poiLocation
.
getLocType
(
)
)
;
sb
.
append
(
"\nlatitude : "
)
;
sb
.
append
(
poiLocation
.
getLatitude
(
)
)
;
sb
.
append
(
"\nlontitude : "
)
;
sb
.
append
(
poiLocation
.
getLongitude
(
)
)
;
sb
.
append
(
"\nradius : "
)
;
sb
.
append
(
poiLocation
.
getRadius
(
)
)
;
if
(
poiLocation
.
getLocType
(
)
==
BDLocation
.
TypeNetWorkLocation
)
{
sb
.
append
(
"\naddr : "
)
;
sb
.
append
(
poiLocation
.
getAddrStr
(
)
)
;
}
if
(
poiLocation
.
hasPoi
(
)
)
{
sb
.
append
(
"\nPoi:"
)
;
sb
.
append
(
poiLocation
.
getPoi
(
)
)
;
}
else
{
sb
.
append
(
"noPoi information"
)
;
}
mTextPoi
.
setText
(
sb
.
toString
(
)
)
;
Log
.
d
(
TAG
,
"onReceiveLocation "
+
sb
.
toString
(
)
)
;
}
}
@Override
public
void
onClick
(
View
v
)
{
// TODO Auto-generated method stub
switch
(
v
.
getId
(
)
)
{
case
R
.
id
.
btn_request
:
if
(
mLocationClient
!=
null
&&
mLocationClient
.
isStarted
(
)
)
mLocationClient
.
requestLocation
(
)
;
else
Log
.
d
(
TAG
,
"locClient is null or not started"
)
;
break
;
case
R
.
id
.
btn_request_poi
:
// 请求POI数据
if
(
mLocationClient
!=
null
&&
mLocationClient
.
isStarted
(
)
)
mLocationClient
.
requestPoi
(
)
;
break
;
default
:
break
;
}
}
}
|
代码说明:
1. 虽然在AndroidManifest.xml里面添加了AK,但是在程序运行中仍然会出现问题,所以在代码中也添加一行
1
|
mLocationClient
.
setAccessKey
(
"uof5MdWhsBtieU4OvMhXQGTm"
)
;
|
2. 官方文档给的demo中,onCreate缺少start(),需要补充,具体见53行高亮代码:
1
|
mLocationClient
.
start
(
)
;
// 开始定位
|
3. 写到这里的时候运行程序,既可以得到你当前的地址,经纬度等其他信息,定位的效果如下:
也可以单独获取省市信息:
1
2
3
4
5
6
7
8
9
10
11
12
|
sb
.
append
(
"\n省份 : "
)
;
sb
.
append
(
location
.
getProvince
(
)
)
;
sb
.
append
(
"\n城市 : "
)
;
sb
.
append
(
location
.
getCity
(
)
)
;
sb
.
append
(
"\n区/县 : "
)
;
sb
.
append
(
location
.
getDistrict
(
)
)
;
sb
.
append
(
"\n街道: "
)
;
sb
.
append
(
location
.
getStreet
(
)
)
;
sb
.
append
(
"\n街道号码: "
)
;
sb
.
append
(
location
.
getStreetNumber
(
)
)
;
sb
.
append
(
"\n地址 : "
)
;
sb
.
append
(
location
.
getAddrStr
(
)
)
;
|