上一篇博文(Hello Baidu Map)记录了如何融合Baidu Map SDK。
可以看到,地图的基本界面,放大和缩小等功能已经呈现。
本文将着重记录自动定位的实现,并简单介绍Optional定位配置和BDLocation对象。
定位当前位置,需要五个步骤。
(1)创建LocationClient对象来初始化定位服务。
private LocationClient m_LocationClient = null;
Context context=getApplicationContext();
m_LocationClient = new LocationClient(context);
(2)使用BDLocationLisenter来接收服务端发来的定位信息。
m_LocationClient.registerLocationListener(this);
public class AroundActivity extends AppCompatActivity implements BDLocationListener
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//Todo
}
@Override
public void onConnectHotSpotMessage(String s, int i) {
//Todo
}
注:仅需实现“onReceiveLocation”方法就好。
“onConnectHotSpotMessage”方法,用于判断连接的wifi是否为移动热点。该方法对于定位功能,意义不大。感兴趣的同学,可以参照SDK Document(文档中也是一点而过),BDLocationListener官方文档。
(3)启动定位服务。
m_LocationClient.start();
注:只有在启动定位服务后,Listener才能得到定位信息。
(4)添加marker来标识当前位置。
到步骤(3)为止,程序已可以获取到当前的位置信息(BDLocation对象)。但尚不能在界面上显示。
百度地图为多层图片层叠合成显示(瓦片图层),若要显示位置信息,需要开启定位图层,或者添加新图层。
private BaiduMap m_Map;
m_Map= mc_Around.getMap();//mc_Around为BaiduMap控件
m_Map.setMyLocationEnabled(true);//若关闭定位图层,则设置为False
封装marker显示方法,并在onReceiveLocation()中调用。
方法1:开启定位图层
private void showCurrentMarker(BDLocation bdLocation){
// 构造定位数据
MyLocationData locData = new MyLocationData.Builder()
.accuracy(bdLocation.getRadius())
.direction(bdLocation.getDirection())
.latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude())
.build(); // 设置定位数据
m_Map.setMyLocationData(locData);
// 设置定位图层的配置(定位模式,是否允许方向信息,用户自定义定位图标)
m_CurrentMarker = BitmapDescriptorFactory
.fromResource(R.mipmap.ic_marker_red);
MyLocationConfiguration config = new MyLocationConfiguration(null, false, m_CurrentMarker);
m_Map.setMyLocationConfiguration(config);
}
注:这里需要对MyLocationConfiguration构造函数的第二个参数进行说明。若为true,marker将显示被定位者的方向,这将影响marker的显示效果(marker可能横着,或者斜着)。
方法2:添加新图层(无需开启定位图层)
private void showCurrentMarker(BDLocation bdLocation){
//定义Maker坐标点,无需开启定位图层
LatLng point = new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude());
//构建Marker图标
BitmapDescriptor bitmap = BitmapDescriptorFactory
.fromResource(R.mipmap.ic_marker_red);
//构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions()
.position(point)
.icon(bitmap);
//在地图上添加Marker,并显示
m_Map.addOverlay(option);
}
自动定位效果如下:
注:定位功能所须权限,已在上一篇博文(Hello Baidu Map)进行了描述,此处不再重复。
(5)设置中心点
从上图效果可以看出,地图画面出现时,当前位置并非在屏幕中心。这对处女座是致命的。
private void setMapCenter(BDLocation bdLocation){
LatLng cenpt = new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude());
//定义地图状态
MapStatus mMapStatus = new MapStatus.Builder().target(cenpt).zoom(18).build();
//定义MapStatusUpdate对象,以便描述地图状态将要发生的变化
MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
//改变地图状态
m_Map .setMapStatus(mMapStatusUpdate);
}
注:zoom()方法,将设置Map的缩放级别。百度地图共有23级缩放。数值越大,定位约详细。实际可用缩放级别为3至21级。
m_Map.setMaxAndMinZoomLevel(MAX_ZOOM,MIN_ZOOM);
至此,自动定位功能实现,但尚未实现实时更新。实时更新部分的实现,可参照本文第二部分,“定位的Optional配置”的相关说明。
定位功能还有很多配置选项,可以通过LocationClientOption对象来设置。
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
option.setCoorType("bd09ll");
//可选,默认gcj02,设置返回的定位结果坐标系
int span=1000;
option.setScanSpan(span);
//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
option.setIsNeedAddress(true);
//可选,设置是否需要地址信息,默认不需要
option.setOpenGps(true);
//可选,默认false,设置是否使用gps
option.setLocationNotify(true);
//可选,默认false,设置是否当GPS有效时按照1S/1次频率输出GPS结果
option.setIsNeedLocationDescribe(true);
//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在XXX附近”
option.setIsNeedLocationPoiList(true);
//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
option.setIgnoreKillProcess(false);
//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
option.SetIgnoreCacheException(false);
//可选,默认false,设置是否收集CRASH信息,默认收集
option.setEnableSimulateGps(false);
//可选,默认false,设置是否需要过滤GPS仿真结果,默认需要
m_LocationClient.setLocOption(option);
注:对于坐标系,有三种选择:bd09ll,bd09,和gcj02(默认)。有时会因为坐标系选择问题,引起定位不准确,导致marker图标无法显示。
注:setScanSpan()方法需要特殊说明。该方法定义了刷新地理位置的间隔时间,该参数以毫秒为单位,须大于等于1000ms才生效。若为0,则只刷新一次。此外,仅当AndroidManifest.xml的Application中进行了如下配置后,方法才能生效。这是一个巨坑!官方文档未找到相关的说明。
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" />
BDLocation对象中还可以获取很多有用的信息。
例如,可以通过调用getLocType()方法,得知信息来源,或者定位异常原因。
BDLocation.TypeGpsLocation //GPS定位
BDLocation.TypeNetWorkLocation//网络定位
BDLocation.TypeOffLineLocation//离线定位
BDLocation.TypeServerError//服务器异常
BDLocation.TypeNetWorkException//网络异常
BDLocation.TypeCriteriaException//手机端异常
还可以获取精度,经纬度等信息。
BDLocation.getTime();//获取定位时间
BDLocation.getLocType();//获取类型类型
BDLocation.getLatitude();//获取纬度信息
BDLocation.getLongitude();//获取经度信息
BDLocation.getRadius();//获取定位精准度
BDLocation.getSpeed();// 单位:公里每小时
BDLocation.getSatelliteNumber();//获取卫星数
BDLocation.BDLocation.getAltitude();//获取海拔高度信息,单位米
BDLocation.BDLocation.getDirection();//获取方向信息,单位度
BDLocation.BDLocation.getAddrStr();//获取地址信息
BDLocation.BDLocation.getOperators();//获取运营商信息
以及POI(Point of Interest)信息,即周边可游玩的去处信息。
List list = bdLocation.getPoiList(); // POI数据
if (list != null) {
for (Poi p : list) {
Log.i(Tags, p.getId() + " " + p.getName() + " " + p.getRank());
}
}
至此,自动定位的功能记录完毕。之后将会总结3D Map模式,及实时通讯功能