上一讲我们介绍了如何在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组件。
1
2
|
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote">
</service>
|
并声明使用权限
1
2
3
4
5
6
7
|
<!-- 使用定位功能所需权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<permission android:name="android.permission.BAIDU_LOCATION_SERVICE"/>
<uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCES_MOCK_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_GPS"/>
|
3、新建相关Activity关实现代码
新建一个类ShowMyLocationActivity继承至Activity,并在AndroidManifest.xml注册。相关代码如下:
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
|
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中添加到该类的”导航”:
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
|
public class MainActivity extends ListActivity {
private Context context;
private String[] demos={"1、显示百度地图","2、在百度地图上显示当前位置"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,demos));
getListView().setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = null;
switch (position) {
case 0:
intent = new Intent(context, ShowMapActivity.class);
break;
case 1:
intent = new Intent(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;
所以下面的代码反而是错误的:
1
2
3
4
5
|
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()中,我们可以使用如下方法判断是否是离线定位请求:
1
2
3
4
5
6
7
8
9
10
11
12
|
@Override
public void onReceiveLocation(BDLocation location) {
if (location==null) {
Toast.makeText(getApplicationContext(), "获取位置信息失败", Toast.LENGTH_LONG).show();
return;
}
if (location.getLocType()==BDLocation.TypeOffLineLocation ) {
//离线定位请求返回的定位结果
}
}
|
原文地址:点击打开链接