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" />

在AndroidManifest.xml中添加

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

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

注意这是在AndroidManifest.xml中的Application中添加,如下:

前期准备完成,接下来就是添加代码

步骤二 添加方向传感器的类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);    }}

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

步骤四 修改布局文件

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"/>

这里用一个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"/>

在Layout布局文件中如图:

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

2. 添加图标

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

提取码:ma06
下载后打开:

全部复制到res文件目录下:

步骤三 添加定位核心代码

1. 开启地图的定位图层

mBaiduMap.setMyLocationEnabled(true);

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);    }}

3. 通过LocationClient发起定位

//定位初始化mLocationClient = new LocationClient(this);//通过LocationClientOption设置LocationClient相关参数LocationClientOption option = new LocationClientOption();option.setOpenGps(true); // 打开gpsoption.setCoorType("bd09ll"); // 设置坐标类型option.setScanSpan(1000);//设置locationClientOptionmLocationClient.setLocOption(option);//注册LocationListener监听器MyLocationListener myLocationListener = new MyLocationListener();mLocationClient.registerLocationListener(myLocationListener);//开启地图定位图层mLocationClient.start();

4. 正确管理各部分的生命周期

@Overrideprotected void onResume() {    mMapView.onResume();    super.onResume();}@Overrideprotected void onPause() {    mMapView.onPause();    super.onPause();}@Overrideprotected void onDestroy() {    mLocationClient.stop();    mBaiduMap.setMyLocationEnabled(false);    mMapView.onDestroy();    mMapView = null;    super.onDestroy();}

以上是百度地图官方文档的说明,读者可以阅读了解。以下是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;            }        });    }}

运行后的效果:

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

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

需要定义一个target变量:

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

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

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

更多相关文章

  1. Android(安卓)高亮指示层提示
  2. android 判断是否有可用网络
  3. Android(安卓)中设置桌面背景
  4. android:windowIsTranslucent
  5. android 创建快捷方式图标到桌面
  6. Android(安卓)动态设置控件高度
  7. android中的滚动条ScrollView
  8. Android运行时动态全屏以及旋转屏幕时不重新装载
  9. 利用GPS定位[android]

随机推荐

  1. 'ADB server didn't ACK'的解决办法
  2. Android_J2meBuilder介绍
  3. Android系统中调试动态链接库.so文件的步
  4. 高德地图自定义Marker点击时出现的InfoWi
  5. 详解Android中自定义View的invalidate,Ha
  6. Android 图片手势缩放自定义View
  7. android中通过"反射"的到android隐藏的AP
  8. gradle更新 build:gradle出错
  9. Android 9.0 (P版本) 亮度控制接口变更
  10. get installed apps info on android and