Android 百度定位SDK(v6.1.3)结合方向传感器
Posted 一口仨馍
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 百度定位SDK(v6.1.3)结合方向传感器相关的知识,希望对你有一定的参考价值。
概述
这是第二篇关于百度地图SDK的博客。
推荐阅读:
Android 百度地图周边雷达(v6.1.3)
今天主要写百度地图定位和方向传感器结合这么一个中间块案例。
流程
- 申请密钥及相关配置请看:http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/buildprojec
- 初始化百度地图SDK
- 定位到当前位置
- 获取方向传感器方向
设定到百度地图SDK
努力总会有收获,go!
为了节省篇幅以及不必要的解释,假设你已经配置好了百度定位SDK。如果没有,请见:http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/buildprojec
按照百度地图SDK,初始化相关组件。
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
testLocation();
在testLocation()里我们注册了mLocationClient的LocationListener以及初始化LocationClientOption。相关代码及详细注释如下
public LocationClient mLocationClient = null;
public BDLocationListener myListener = new MyLocationListener();
private void testLocation()
mLocationClient = new LocationClient(getApplicationContext()); //声明LocationClient类
mLocationClient.registerLocationListener(myListener); //注册监听函数
/**
* 高精度定位模式:这种定位模式下,会同时使用网络定位和GPS定位,优先返回最高精度的定位结果;
* 低功耗定位模式:这种定位模式下,不会使用GPS,只会使用网络定位(Wi-Fi和基站定位);
* 仅用设备定位模式:这种定位模式下,不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位。
*/
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有效时按照1S1次频率输出GPS结果
option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
option.setIgnoreKillProcess(false);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
option.SetIgnoreCacheException(true);//可选,默认false,设置是否收集CRASH信息,默认收集
option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤gps仿真结果,默认需要
mLocationClient.setLocOption(option);
细心的同学会看到,这里我们实现了一个自己的Listener。
private class MyLocationListener implements BDLocationListener
@Override
public void onReceiveLocation(BDLocation location)
//mapview 销毁后不在处理新接收的位置
if (location == null || mBaiduMap == null)
return;
getLocationInfo(location);
// 开启定位图层
mBaiduMap.setMyLocationEnabled(true);
// 构造定位数据
final MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
// 设置定位数据
mBaiduMap.setMyLocationData(locData);
if (isFirstGetLocation)
isFirstGetLocation = false;
// 获取经纬度
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
// 设置地图中心点以及缩放级别
MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, 15);
mBaiduMap.animateMapStatus(mapStatusUpdate);
// Log.i(TAG, "latitude:"+mBaiduMap.getLocationData().latitude +
// "\\nlongitude:"+mBaiduMap.getLocationData().longitude +
// "\\ndirection:"+mBaiduMap.getLocationData().direction);
// 设置定位图层的配置(定位模式,是否允许方向信息,用户自定义定位图标)
mCurrentMarker = BitmapDescriptorFactory.fromResource(R.mipmap.location_pic);
MyLocationConfiguration config = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL,
true, mCurrentMarker);
mBaiduMap.setMyLocationConfigeration(config);
我们的listener实现了BDLocationListener接口。复写了onReceiveLocation()方法。就像方法的名字,收到定位信息后会调用此方法。因此,在此方法里我们可以实现收到定位信息后自己的逻辑。这样我们就有了一个最初始的百度地图。位置更详细的信息在getLocationInfo()方法里。一般需要的信息都可以在此找到。
private void getLocationInfo(BDLocation location)
//Receive Location
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) // GPS定位结果
sb.append("\\nspeed : ");
sb.append(location.getSpeed());// 单位:公里每小时
sb.append("\\nsatellite : ");
sb.append(location.getSatelliteNumber());
sb.append("\\nheight : ");
sb.append(location.getAltitude());// 单位:米
sb.append("\\ndirection : ");
sb.append(location.getDirection());// 单位度
sb.append("\\naddr : ");
sb.append(location.getAddrStr());
sb.append("\\ndescribe : ");
sb.append("gps定位成功");
else if (location.getLocType() == BDLocation.TypeNetWorkLocation) // 网络定位结果
sb.append("\\naddr : ");
sb.append(location.getAddrStr());
//运营商信息
sb.append("\\noperationers : ");
sb.append(location.getOperators());
sb.append("\\ndescribe : ");
sb.append("网络定位成功");
else if (location.getLocType() == BDLocation.TypeOffLineLocation) // 离线定位结果
sb.append("\\ndescribe : ");
sb.append("离线定位成功,离线定位结果也是有效的");
else if (location.getLocType() == BDLocation.TypeServerError)
sb.append("\\ndescribe : ");
sb.append("服务端网络定位失败,可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com,会有人追查原因");
else if (location.getLocType() == BDLocation.TypeNetWorkException)
sb.append("\\ndescribe : ");
sb.append("网络不同导致定位失败,请检查网络是否通畅");
else if (location.getLocType() == BDLocation.TypeCriteriaException)
sb.append("\\ndescribe : ");
sb.append("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机");
sb.append("\\nlocationdescribe : ");
sb.append(location.getLocationDescribe());// 位置语义化信息,结果类似于“在北京天安门附近”
List<Poi> list = location.getPoiList();// POI数据
if (list != null)
sb.append("\\npoilist size = : ");
sb.append(list.size());
for (Poi p : list)
sb.append("\\npoi= : ");
sb.append(p.getId() + " " + p.getName() + " " + p.getRank());
Log.i(TAG, sb.toString());
至此,我们百度定位SDK的就完事了。假设我们想做到旋转手机的时候旋转location_pic对应的方向怎么办呢?答案就是结合方向传感器啦!中间体,这也是本篇博客的主要所在。
方向传感器简介
- 手机的自然坐标系
当一个设备被放在其默认的方向上时,X轴是水平指向右的,Y轴是垂直向上的,Z轴是指向屏幕正面之外的,即屏幕背面是Z的负值。
- 方向传感器是利用加速度计和地磁场传感器得到自己的数据。方向传感器比较特殊,因为它的数值是相对于绝对方向的。它得到的是手机设备的绝对姿态值。
方向传感器返回的都是角度值,以度数为单位。
我们只用到X轴坐标:表示手机自身的y轴与地磁场北极方向的角度,即手机顶部朝向与正北方向的角度。(This is the angle between magnetic north and the device’s y axis. )当手机绕着自身的z轴旋转时,该角度值将发生改变。例如该角度值为0时,表示手机顶部指向正北;该角度为90度时,代表手机顶部指向正东;该角度为180度时,代表手机顶部指向正南;该角度为270度时,代表手机顶部指向正西。
写一个自己的方向传感器
package com.dyk.baidumapwork;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
/**
* Created by dyk on 2016/3/22.
*/
public class OrientationSensor implements SensorEventListener
private static final String TAG = "BaiduMap";
private Context mContext;
private SensorManager mSensorManager;
private Sensor defaultSensor;
private float lastX;
private OrientationSensorListener mOrientationSensorListener;
public OrientationSensor(Context context)
this.mContext = context;
public void start()
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
defaultSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
mSensorManager.registerListener(this, defaultSensor, SensorManager.SENSOR_DELAY_NORMAL);
public void stop()
mSensorManager.unregisterListener(this, defaultSensor);
@Override
public void onSensorChanged(SensorEvent event)
Log.i(TAG,event.values[0]+" "+event.values[1]+" "+event.values[2]);
if (mOrientationSensorListener != null && (Math.abs(event.values[0] - lastX)) > 1)
mOrientationSensorListener.getOrientation(event.values[0]);
lastX = event.values[0];
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
public interface OrientationSensorListener
void getOrientation(float x);
public void setOrientationListener(OrientationSensorListener orientationSensorListener)
this.mOrientationSensorListener = orientationSensorListener;
可以看到,在此我们实现了SensorEventListener接口,并复写了onSensorChanged()和onAccuracyChanged()方法。这里我们用到onSensorChanged的参数event.values[0]获取X轴坐标。这里尴尬的事情来了,这里不断的变化,怎么传递给activity?接口!
这里我们定义了一个OrientationSensorListener接口,只有一个方法。getOrientation(float x)
private OrientationSensorListener mOrientationSensorListener;
public interface OrientationSensorListener
void getOrientation(float x);
public void setOrientationListener(OrientationSensorListener orientationSensorListener)
this.mOrientationSensorListener = orientationSensorListener;
在onSensorChanged()方法中我们可以调用OrientationSensorListener#getOrientation(float x),并且把X轴坐标event.values[0]当做参数传递进去,接着在activity里实现接口,获取数据,设定方向。代码如下
private OrientationSensor mOrientationSensor;
/**
* 传感器方向
*/
private float driection = 0;
mOrientationSensor = new OrientationSensor(this);
mOrientationSensor.start();
private class MyLocationListener implements BDLocationListener
@Override
public void onReceiveLocation(BDLocation location)
mOrientationSensor.setOrientationListener(new OrientationSensor.OrientationSensorListener()
@Override
public void getOrientation(float x)
driection = x;
);
final MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(driection)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
Log.i(TAG, "driection=" + driection);
// 设置定位数据
mBaiduMap.setMyLocationData(locData);
至此就成功的将方向传感器的数据传递到了百度地图中。最后不要忘了释放资源。
@Override
protected void onDestroy()
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
mMapView.onDestroy();
if (mLocationClient.isStarted())
mLocationClient.stop();
if (mBaiduMap.isMyLocationEnabled())
// 当不需要定位图层时关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
//反注册OrientationSensor
if (mOrientationSensor != null)
mOrientationSensor.stop();
欢迎访问我的博客及另外两篇关于百度地图SDK的博文,综合使用可以实现更多效果:
Demo全部代码及资源下载:http://download.csdn.net/detail/qq_17250009/9469613
以上是关于Android 百度定位SDK(v6.1.3)结合方向传感器的主要内容,如果未能解决你的问题,请参考以下文章