Android 百度定位SDK(v6.1.3)结合方向传感器

简介:

概述

这是第二篇关于百度地图SDK的博客。

推荐阅读:
Android 百度地图周边雷达(v6.1.3)

Android 百度鹰眼轨迹SDK(v2.1.6)

今天主要写百度地图定位和方向传感器结合这么一个中间块案例。

流程

  1. 申请密钥及相关配置请看:http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/buildprojec
  2. 初始化百度地图SDK
  3. 定位到当前位置
  4. 获取方向传感器方向
  5. 设定到百度地图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对应的方向怎么办呢?答案就是结合方向传感器啦!中间体,这也是本篇博客的主要所在。

方向传感器简介

  1. 手机的自然坐标系
    当一个设备被放在其默认的方向上时,X轴是水平指向右的,Y轴是垂直向上的,Z轴是指向屏幕正面之外的,即屏幕背面是Z的负值
    sensor
  2. 方向传感器是利用加速度计和地磁场传感器得到自己的数据。方向传感器比较特殊,因为它的数值是相对于绝对方向的。它得到的是手机设备的绝对姿态值。
    方向传感器返回的都是角度值,以度数为单位。

我们只用到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的博文,综合使用可以实现更多效果:

  1. 我的博客

  2. Android 百度地图周边雷达(v6.1.3)及覆盖物

  3. Android 百度鹰眼轨迹SDK(v2.1.6)

Demo全部代码及资源下载:http://download.csdn.net/detail/qq_17250009/9469613

相关文章
|
21天前
|
JavaScript Java Maven
云效产品使用常见问题之android sdk 构建出aar后,上传到私有maven仓库失败如何解决
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
4月前
|
安全 开发工具 Android开发
几个Flutter常见诊断错误与解决Android toolchain - develop for Android devices X Unable to locate Android SDK
几个Flutter常见诊断错误与解决Android toolchain - develop for Android devices X Unable to locate Android SDK
422 0
|
7月前
|
API 开发工具 Android开发
解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
152 0
|
20天前
|
传感器 Android开发
Android MediaTek 添加LPS22HB压力传感器驱动
Android MediaTek 添加LPS22HB压力传感器驱动
5 0
|
4月前
|
开发工具 Android开发
Android获取SDK的版本信息
Android获取SDK的版本信息
44 0
|
5月前
|
传感器 物联网 Android开发
【Android App】物联网中查看手机支持的传感器及实现摇一摇功能-加速度传感器(附源码和演示 超详细)
【Android App】物联网中查看手机支持的传感器及实现摇一摇功能-加速度传感器(附源码和演示 超详细)
74 1
|
5月前
|
编解码 Java 开发工具
Android端接入视频生产 Java SDK
Android端接入视频生产 Java SDK
43 1
|
5月前
|
监控 Java 开发工具
基于Eclipse+SDK+ADT+DDMS的安卓开发环境完整搭建过程
基于Eclipse+SDK+ADT+DDMS的安卓开发环境完整搭建过程
47 0
基于Eclipse+SDK+ADT+DDMS的安卓开发环境完整搭建过程
|
Java 语音技术 开发工具
Android 讯飞离线语音听写/离线语音识别SDK
Android 讯飞离线语音听写/离线语音识别SDK
401 0
Android 讯飞离线语音听写/离线语音识别SDK
|
9月前
|
Java 开发工具 Android开发
逻辑清晰,详解社交源码Android开发SDK
前篇我们讲解了有关如何在IOS平台开发集成SDK,那么今天来给大家简单讲解下如何在社交源码Android客户端上开发集成 SDK。
逻辑清晰,详解社交源码Android开发SDK