Android(安卓)studio百度地图SDK开发 2020最新超详细的Android(安卓)百度地图开发讲解(2) 实时定位的实现,配合方向传感器
2020最新超详细的Android 百度地图开发讲解(2) 实时定位的实现,配合方向传感器
来自百度地图官方平台关于坐标系的说明:
Android定位SDK产品,支持全球定位,能够精准的获取经纬度信息。根据开发者的设置,在国内获得的坐标系类型可以是:国测局坐标、百度墨卡托坐标 和 百度经纬度坐标。在海外地区,只能获得WGS84坐标。请开发者在使用过程中注意坐标选择。定位SDK默认输出GCJ02坐标,地图SDK默认输出BD09ll坐标。
实现定位是百度地图开发的第二大基本内容,我在一开始做的时候遇到了挺多坑,主要是因为对代码不熟悉,而且基本是照搬其他博客的代码,所以遇到了一些bug自己很难解决,只有不停的查百度。后来多做了几次之后就基本没出问题了。建议参照百度地图官方开发文档,里面功能介绍还是比较全的,但是不适合刚起步的小白,可以用来了解代码功能,然后具体怎么用看下面的操作过程。尽可能把每一步都说明清楚。
实现定位前的准备
步骤一 添加权限和声明定位的serves组件
- 在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
更多相关文章
- Android(安卓)高亮指示层提示
- android 判断是否有可用网络
- Android(安卓)中设置桌面背景
- android:windowIsTranslucent
- android 创建快捷方式图标到桌面
- Android(安卓)动态设置控件高度
- android中的滚动条ScrollView
- Android运行时动态全屏以及旋转屏幕时不重新装载
- 利用GPS定位[android]