当前位置:   article > 正文

Android studio百度地图SDK开发 2020最新超详细的Android 百度地图开发讲解(2) 实时定位的实现,配合方向传感器_百度地图 实时追踪 开发

百度地图 实时追踪 开发

2020最新超详细的Android 百度地图开发讲解(2) 实时定位的实现,配合方向传感器

来自百度地图官方平台关于坐标系的说明:
Android定位SDK产品,支持全球定位,能够精准的获取经纬度信息。根据开发者的设置,在国内获得的坐标系类型可以是:国测局坐标、百度墨卡托坐标 和 百度经纬度坐标。在海外地区,只能获得WGS84坐标。请开发者在使用过程中注意坐标选择。定位SDK默认输出GCJ02坐标,地图SDK默认输出BD09ll坐标。

实现定位是百度地图开发的第二大基本内容,我在一开始做的时候遇到了挺多坑,主要是因为对代码不熟悉,而且基本是照搬其他博客的代码,所以遇到了一些bug自己很难解决,只有不停的查百度。后来多做了几次之后就基本没出问题了。建议参照百度地图官方开发文档,里面功能介绍还是比较全的,但是不适合刚起步的小白,可以用来了解代码功能,然后具体怎么用看下面的操作过程。尽可能把每一步都说明清楚。

实现定位前的准备

步骤一 添加权限和声明定位的serves组件

  1. 在AndroidManifest.xml中添加定位权限
    这个必须有,不能少。需要添加的权限如下:
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  • 1
  • 2
  • 3
  • 4

在AndroidManifest.xml中添加
在AndroidManifest.xml中添加后
2. 在AndroidManifest.xml中添加serves组件

<service android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote"/>
  • 1
  • 2
  • 3

注意这是在AndroidManifest.xml中的Application中添加,如下:
在AndroidManifest.xml中添加
前期准备完成,接下来就是添加代码

步骤二 添加方向传感器的类MyOrientationListener

方向传感器的类就是能够感应方向,实时调节箭头的指向。
代码如下:


public class MyOrientationListener implements SensorEventListener
{
    private SensorManager mSensorManager;
    private Context mContext;
    private Sensor mSensor;
    private float lastX;

    public MyOrientationListener(Context context)
    {
        this.mContext = context;
    }

    @SuppressWarnings("deprecation")
    public void start()
    {
        mSensorManager = (SensorManager) mContext
                .getSystemService(Context.SENSOR_SERVICE);
        if (mSensorManager != null)
        {
            // 获得方向传感器
            mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        }

        if (mSensor != null)
        {
            mSensorManager.registerListener(this, mSensor,
                    SensorManager.SENSOR_DELAY_UI);
        }
    }

    public void stop()
    {
        mSensorManager.unregisterListener(this);
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1)
    {
        // TODO Auto-generated method stub

    }

    @SuppressWarnings(
            { "deprecation" })
    @Override
    public void onSensorChanged(SensorEvent event)
    {
        if (event.sensor.getType() == Sensor.TYPE_ORIENTATION)
        {
            float x = event.values[SensorManager.DATA_X];

            if (Math.abs(x - lastX) > 1.0)
            {
                if (mOnOrientationListener != null)
                {
                    mOnOrientationListener.onOrientationChanged(x);
                }
            }

            lastX = x;

        }
    }

    private OnOrientationListener mOnOrientationListener;

    public void setOnOrientationListener(
            OnOrientationListener mOnOrientationListener)
    {
        this.mOnOrientationListener = mOnOrientationListener;
    }

    public interface OnOrientationListener
    {
        void onOrientationChanged(float x);
    }

}

  • 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

这就是一个正常的类,直接复制粘贴即可。不用创建Layout布局文件。注意放在和MainActivity或者你需要实现定位的Activity同一个包中,不过不是必须。
MyOrientationListener

步骤四 修改布局文件

1. 设置布局文件

在需要实现定位的布局文件中添加如下空间,以回到当前定位。

<ImageView
            android:id="@+id/image_loc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/pic_locate_init"
            android:layout_marginTop="540dp"
            android:layout_marginLeft="320dp"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里用一个ImageView来做为回到当前定位的button,图标样式:
在这里插入图片描述
也可以自己设置成其他button或者其他样式。
Button代码如下:

<Button
        android:id="@+id/but_Loc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="定位"
        android:layout_marginLeft="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="127dp"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在Layout布局文件中如图:
布局文件中的代码
为了让image可以在地图右下角展示我将地图控件和image空降放在了同一个RelativeLayout相对布局里面。
效果如下:
效果

2. 添加图标

定位资源图标下载:链接:https://pan.baidu.com/s/1tWRIM53g8_HIHniUOFAhiQ

提取码:ma06
下载后打开:
在这里插入图片描述
全部复制到res文件目录下:
添加后

步骤三 添加定位核心代码

1. 开启地图的定位图层
mBaiduMap.setMyLocationEnabled(true);
  • 1
2. 构造地图数据

我们通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。

public class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            //mapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null){
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    // 此处设置开发者获取到的方向信息,顺时针0-360
                    .direction(location.getDirection()).latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            mBaiduMap.setMyLocationData(locData);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
3. 通过LocationClient发起定位
//定位初始化
mLocationClient = new LocationClient(this);

//通过LocationClientOption设置LocationClient相关参数
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);

//设置locationClientOption
mLocationClient.setLocOption(option);

//注册LocationListener监听器
MyLocationListener myLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(myLocationListener);
//开启地图定位图层
mLocationClient.start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
4. 正确管理各部分的生命周期
@Override
protected void onResume() {
    mMapView.onResume();
    super.onResume();
}

@Override
protected void onPause() {
    mMapView.onPause();
    super.onPause();
}

@Override
protected void onDestroy() {
    mLocationClient.stop();
    mBaiduMap.setMyLocationEnabled(false);
    mMapView.onDestroy();
    mMapView = null;
    super.onDestroy();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

以上是百度地图官方文档的说明,读者可以阅读了解。以下是MainActivity中的完整代码:

定位完整代码

相对于官方文档有一定的修改:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private MapView mMapView = null;
    private BaiduMap mBaiduMap = null;
    private Context context;

    //定位相关
    private double mLatitude;
    private double mLongtitude;

    //方向传感器
    private MyOrientationListener mMyOrientationListener;
    private float mCurrentX;
    //自定义图标
    private BitmapDescriptor mIconLocation;
    private LocationClient mLocationClient;
    public BDAbstractLocationListener myListener;
    private LatLng mLastLocationData;
    private boolean isFirstin = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);
        SDKInitializer.setCoordType(CoordType.BD09LL);
        this.context = this;
        mMapView = (MapView) findViewById(R.id.bmapView);
        //获取地图控件引用
        mBaiduMap = mMapView.getMap();
        initMyLocation();
        button();
    }
    protected void onStart() {
        super.onStart();
        //开启定位
        mBaiduMap.setMyLocationEnabled(true);
        if (!mLocationClient.isStarted())
            mLocationClient.start();
        //开启方向传感器
        mMyOrientationListener.start();
    }
    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        mMapView.onPause();
    }
    @Override
    protected void onStop() {
        super.onStop();
        //停止定位
        mBaiduMap.setMyLocationEnabled(false);
        mLocationClient.stop();
        //停止方向传感器
        mMyOrientationListener.stop();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBaiduMap.setMyLocationEnabled(false);
        mMapView.onDestroy();
        mMapView = null;
    }
    @Override
    public void onClick(View v) {
        SDKInitializer.initialize(getApplicationContext());
        switch (v.getId()) {
            case R.id.image_loc: {
                centerToMyLocation(mLatitude, mLongtitude);
                break;
            }
        }
    }

    //按钮响应
    private void button() {
        //按钮
        Button mbut_Loc = (Button) findViewById(R.id.image_loc);
        //按钮处理
        mbut_Loc.setOnClickListener(this);
    }

    //定位
    private class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            //mapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null){
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    // 此处设置开发者获取到的方向信息,顺时针0-360
                    .direction(mCurrentX).latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            mBaiduMap.setMyLocationData(locData);
            //设置自定义图标
            MyLocationConfiguration config = new
                    MyLocationConfiguration(
                    MyLocationConfiguration.LocationMode.NORMAL, true, mIconLocation);
            mBaiduMap.setMyLocationConfiguration(config);
            //更新经纬度
            mLatitude = location.getLatitude();
            mLongtitude = location.getLongitude();
            //设置起点
            mLastLocationData = new LatLng(mLatitude, mLongtitude);
            if (isFirstin) {
                centerToMyLocation(location.getLatitude(), location.getLongitude());

                if (location.getLocType() == BDLocation.TypeGpsLocation) {
                    // GPS定位结果
                    Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                    // 网络定位结果
                    Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
                    // 离线定位结果
                    Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeServerError) {
                    Toast.makeText(context, "定位:服务器错误", Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                    Toast.makeText(context, "定位:网络错误", Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                    Toast.makeText(context, "定位:手机模式错误,请检查是否飞行", Toast.LENGTH_SHORT).show();
                }
                isFirstin = false;
            }
        }
    }
    //初始化定位
    private void initMyLocation() {
        //缩放地图
        MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
        mBaiduMap.setMapStatus(msu);
        //开启定位
        mBaiduMap.setMyLocationEnabled(true);
        //声明LocationClient类
        mLocationClient = new LocationClient(this);
        //通过LocationClientOption设置LocationClient相关参数
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true); // 打开gps
        option.setCoorType("bd09ll"); // 设置坐标类型
        option.setIsNeedAddress(true);//设置是否需要地址信息
        option.setScanSpan(1000);
        //设置locationClientOption
        mLocationClient.setLocOption(option);
        myListener = new MyLocationListener();
        //注册监听函数
        mLocationClient.registerLocationListener(myListener);
        //初始化图标
        mIconLocation = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps);
        initOrientation();
        //开始定位
        mLocationClient.start();
    }
    //回到定位中心
    private void centerToMyLocation(double latitude, double longtitude) {
        mBaiduMap.clear();
        mLastLocationData = new LatLng(latitude, longtitude);
        MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(mLastLocationData);
        mBaiduMap.animateMapStatus(msu);
    }
    //传感器
    private void initOrientation() {
        //传感器
        mMyOrientationListener = new MyOrientationListener(context);
        mMyOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
            @Override
            public void onOrientationChanged(float x) {
                mCurrentX = x;
            }
        });
    }
}
  • 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
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179

运行后的效果:
定位结果
第一次运行时会显示请求定位权限的弹窗,全部同意,然后可能会定位到几内亚湾,因为在还没同意权限前,后台定位就完成了,但是定位失败,就飞到了几内亚湾。点击定位按钮 Image,就回到了当前定位。 如果不希望在没有开启定位时出现飞到几内亚湾的情况,可以设置初始定位地址。代码如下:

//设置地图默认定位位置,地图中心位target的经纬度
        MapStatusUpdate mapStatusUpdate= MapStatusUpdateFactory.newLatLng(target);
        InitialBaiduMap.setMapStatus(mapStatusUpdate);
  • 1
  • 2
  • 3

需要定义一个target变量:

//设置变量target,表示默认定位的地方 默认地点华理
    protected LatLng target = new LatLng(30.83673,121.510342);
  • 1
  • 2

代码图

——————————————————————————
版权所有,转载请标明出处

借鉴的博客:
https://blog.csdn.net/qq_38605488/article/details/87040264
官方文档:
http://lbsyun.baidu.com/index.php?title=androidsdk/guide/create-map/location

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/297545
推荐阅读
相关标签
  

闽ICP备14008679号