android百度地图开发——地图sdk之基础地图

来源:互联网 发布:钓鱼王vb强食剂 编辑:程序博客网 时间:2024/05/17 00:57

上一节我们介绍了百度定位sdk,这一节我们在定位的基础上介绍百度地图sdk。

让地图显示出来

首先把上一节布局文件中添加的textview删掉,然后加入MapView这个控件:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.example.lbstest.MainActivity">    <com.baidu.mapapi.map.MapView        android:id="@+id/mapView"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:clickable="true"/></android.support.constraint.ConstraintLayout>

毫无疑问这个控件就是显示地图的。
接着我们对Activity做以下修改:

    private MapView mMapView;    private BaiduMap mBaiduMap;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mlocation = new LocationClient(getApplicationContext());        mlocation.registerLocationListener(new MyLocationListener());        SDKInitializer.initialize(getApplicationContext());        setContentView(R.layout.activity_main);        //初始化方向传感器        myOrientationListener = new MyOrientationListener(this);        //获取地图控件引用        mMapView = (MapView) findViewById(R.id.mapView);        mBaiduMap = mMapView.getMap();        //申请权限        initPermission();    }    @Override    protected void onResume() {        super.onResume();        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理        mMapView.onResume();    }    @Override    protected void onPause() {        super.onPause();        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理        mMapView.onPause();    }    @Override    protected void onDestroy() {        super.onDestroy();        mlocation.stop();        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理        mMapView.onDestroy();    }

和上一节相比多了SDKInitializer初始化、获取MapView实例和获取BaiduMap的实例(BaiduMap是地图的总控制器,它可以对地图进行各种各样的操作),另外还需要重写onDestroy() 、onPause()、 onResume() 这3个方法对MapView进行管理,以保证资源能够及时释放。到这里地图已经能够显示出来了。

显示当前位置

聪明的你一定发现我们并没有设置坐标,这样是不能显示到我们的位置的, 下面我们让地图显示到我们的位置。
这就需要我们上一节中定位sdk的知识了,首先我们把BDLocationListener做一下修改:

public class MyLocationListener implements BDLocationListener {        @Override        public void onReceiveLocation(BDLocation bdLocation) {            mCurrentAccracy=bdLocation.getRadius();            mCurrentLantitude=bdLocation.getLatitude();            mCurrentLongitude=bdLocation.getLongitude();            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation || bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {                //设置地图显示                navigateTo(bdLocation);            }        }        @Override        public void onConnectHotSpotMessage(String s, int i) {        }    }    private void navigateTo(BDLocation location) {        if (isFirstLocate) {            //定位坐标            LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);            mBaiduMap.animateMapStatus(update);            //设置缩放级别            update = MapStatusUpdateFactory.zoomTo(21f);            mBaiduMap.animateMapStatus(update);            isFirstLocate = false;        }    }

上面的代码首先在定位回调的函数中将经纬度信息赋值给全局变量,这是在后面使用的我们暂时不看,然后判断是否定位成功,成功后调用navigateTo()方法,在navigateTo()方法中通过一个boolean全局变量判断是否是第一次定位,然户设置定位坐标,缩放级别(其他的设置属性参照官方文档,这里就不多介绍了),现在地图就已经显示在我们的位置了。

运行效果:
这里写图片描述

显示定位图标

我们用的地图都会有一个图标显示在我们的位置,下面我们来添加这个图标。
首先要在onCreate()方法中调用BaiduMap的setMyLocationEnabled方法开启此功能:

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mlocation = new LocationClient(getApplicationContext());        mlocation.registerLocationListener(new MyLocationListener());        SDKInitializer.initialize(getApplicationContext());        setContentView(R.layout.activity_main);        //初始化方向传感器        myOrientationListener = new MyOrientationListener(this);        //获取地图控件引用        mMapView = (MapView) findViewById(R.id.mapView);        mBaiduMap = mMapView.getMap();        mBaiduMap.setMyLocationEnabled(true);        //申请权限        initPermission();    }

接着在navigateTo方法中添加MyLocationData的构建逻辑:

    private void navigateTo(BDLocation location) {        if (isFirstLocate) {            //定位坐标            LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);            mBaiduMap.animateMapStatus(update);            //设置缩放级别            update = MapStatusUpdateFactory.zoomTo(21f);            mBaiduMap.animateMapStatus(update);            isFirstLocate = false;        }        MyLocationData.Builder builder = new MyLocationData.Builder();                builder.accuracy(mCurrentAccracy);                builder.latitude(mCurrentLantitude);                builder.longitude(mCurrentLongitude);                MyLocationData locationData = builder.build();                mBaiduMap.setMyLocationData(locationData);    }

这里用到了mCurrentAccracy、mCurrentLantitude、mCurrentLongitude这三个保存了经纬度信息的全局变量,MyLocationConfiguration 的最后一个参数设置图标的样式,传入空为默认图标,当然也可以传入一个BitmapDescriptor设置自定义图标。
最后在onDestroy()方法中关闭此功能:

    @Override    protected void onDestroy() {        super.onDestroy();        mlocation.stop();        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理        mMapView.onDestroy();        mBaiduMap.setMyLocationEnabled(false);    }

到这里显示定位图标就完成了。

运行效果:
这里写图片描述

定位图标与传感器结合显示方向

虽然当前位置的图标显示出来了,但是对于一些路痴来说(比如我)仍然找不到方向,这就需要显示方向了,显示方向的功能实现需要手机的加速度和地磁场传感器,根据这两个传感器计算出手机的角度,然后将这个角度传给MyLocationData.Builder的builder.direction()方法用于设置方向。下面我们开始实现这一功能。
在往下看之前建议先看一下一篇关于传感器的文章:http://www.2cto.com/kf/201412/359292.html

首先创建一个类MyOrientationListener,所有传感器的操作都封装在这个类中:

public class MyOrientationListener implements SensorEventListener {    private Context context;    private SensorManager sensorManager;    private Sensor accelerometer; // 加速度传感器    private Sensor magnetic; // 地磁场传感器    private float[] accelerometerValues = new float[3];    private float[] magneticFieldValues = new float[3];    private float lastX;    private OnOrientationListener onOrientationListener ;    public MyOrientationListener(Context context)    {        this.context = context;    }    @Override    public void onSensorChanged(SensorEvent event) {        // 接受方向感应器的类型        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {            accelerometerValues = event.values;        }        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {            magneticFieldValues = event.values;        }        getOrientation();    }    public void getOrientation() {        float[] values = new float[3];        float[] R = new float[9];        SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticFieldValues);        //将角度信息计算后返回到values中        SensorManager.getOrientation(R, values);        values[0] = (float) Math.toDegrees(values[0]);        //当方向的改变大于一度时回调监听        if( Math.abs(values[0]- lastX) > 1.0 )        {            onOrientationListener.onOrientationChanged(values[0]);        }        lastX = values[0] ;    }    @Override    public void onAccuracyChanged(Sensor sensor, int accuracy) {    }    public void start(){        // 获得传感器管理器        sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);        if (sensorManager != null)        {            // 初始化加速度传感器            accelerometer = sensorManager                    .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);            // 初始化地磁场传感器            magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);        }        // 注册        if (accelerometer != null || magnetic!=null)        {            sensorManager.registerListener(this,                    accelerometer, Sensor.TYPE_ACCELEROMETER);            sensorManager.registerListener(this, magnetic,                    Sensor.TYPE_MAGNETIC_FIELD);        }    }    public void stop() {        sensorManager.unregisterListener(this);    }    public void setOnOrientationListener(OnOrientationListener onOrientationListener) {        this.onOrientationListener = onOrientationListener;    }    public interface OnOrientationListener{        void onOrientationChanged(float x);    }}

如果你看了我推荐的那篇文章上面的代码对你来说就是小菜一碟,注释也写得清楚我就不详细介绍了,使用时只需创建一个实例,然后调用start()方法,在设置监听就可以了,最后别忘了stop()。
我们在我们Activity实现这个类:
首先在oncreat()方法中实例化这个类,并设置监听,把接收的参数赋值给一个全局变量:

   @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mlocation = new LocationClient(getApplicationContext());        mlocation.registerLocationListener(new MyLocationListener());        SDKInitializer.initialize(getApplicationContext());        setContentView(R.layout.activity_main);        //初始化方向传感器        myOrientationListener = new MyOrientationListener(this);        myOrientationListener.setOnOrientationListener(this);        //获取地图控件引用        mMapView = (MapView) findViewById(R.id.mapView);        mBaiduMap = mMapView.getMap();        mBaiduMap.setMyLocationEnabled(true);        //申请权限        initPermission();    }

接着在onResume()方法中调用MyOrientationListener的start()方法:

    @Override    protected void onResume() {        super.onResume();        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理        mMapView.onResume();        myOrientationListener.start();    }

然后把navigateTo()方法中对MyLocationData.Builder的配置删掉:

 private void navigateTo(BDLocation location) {        if (isFirstLocate) {            //定位坐标            LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);            mBaiduMap.animateMapStatus(update);            //设置缩放级别            update = MapStatusUpdateFactory.zoomTo(21f);            mBaiduMap.animateMapStatus(update);            isFirstLocate = false;        }    }

最后在MyOrientationListener的监听方法中添加以下代码:

    @Override    public void onOrientationChanged(float x) {        mXDirection = (int) x;        builder = new MyLocationData.Builder();        builder.accuracy(mCurrentAccracy);        builder.direction(mXDirection);        builder.latitude(mCurrentLantitude);        builder.longitude(mCurrentLongitude);        MyLocationData locationData = builder.build();        mBaiduMap.setMyLocationData(locationData);        // 设置自定义图标        //BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory.fromResource(R.drawable.arrow);        MyLocationConfiguration configuration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, null);        mBaiduMap.setMyLocationConfiguration(configuration);    }

我们对MyLocationData增加了一个设置builder.direction(mXDirection)。最后还要用MyLocationConfiguration对BaiduMap进行配置,MyLocationConfiguration的第一个参数为图标显示模式,有三种模式我就不一一介绍了,有兴趣的同学可以自己试试,或者参考官方文档,第二个参数表示是否显示方向,第三个参数为自定义图标,如果使用默认图标传入空就行了。

最后别忘了在onDestroy()方法中stop方向传感器:

 @Override    protected void onDestroy() {        super.onDestroy();        mlocation.stop();        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理        mMapView.onDestroy();        mBaiduMap.setMyLocationEnabled(false);    }

运行效果:
这里写图片描述

到这里百度地图sdk的初使用也完成了,下面是完整的代码:

public class MainActivity extends AppCompatActivity implements MyOrientationListener.OnOrientationListener{    private MapView mMapView;    private BaiduMap mBaiduMap;    private List<String> permissionList;    private Boolean isFirstLocate=true;    private float mCurrentAccracy;    private double mCurrentLantitude;    private double mCurrentLongitude;    private int mXDirection;    public LocationClient mlocation;    private MyLocationData.Builder builder;    private MyOrientationListener myOrientationListener;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mlocation = new LocationClient(getApplicationContext());        mlocation.registerLocationListener(new MyLocationListener());        SDKInitializer.initialize(getApplicationContext());        setContentView(R.layout.activity_main);        //初始化方向传感器        myOrientationListener = new MyOrientationListener(this);        myOrientationListener.setOnOrientationListener(this);        //获取地图控件引用        mMapView = (MapView) findViewById(R.id.mapView);        mBaiduMap = mMapView.getMap();        mBaiduMap.setMyLocationEnabled(true);        //申请权限        initPermission();    }    private void initPermission() {        permissionList = new ArrayList<>();        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);        }        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {            permissionList.add(Manifest.permission.READ_PHONE_STATE);        }        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);        }        if (!permissionList.isEmpty()) {            String[] permissions = permissionList.toArray(new String[permissionList.size()]);            ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);        } else {            //请求定位            requestLocation();        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        switch (requestCode) {            case 1:                if (grantResults.length > 0) {                    for (int result : grantResults) {                        if (result != PackageManager.PERMISSION_GRANTED) {                            Toast.makeText(MainActivity.this, "必须同意所有权限", Toast.LENGTH_LONG).show();                            finish();                            return;                        }                    }                    //请求定位                    requestLocation();                } else {                    finish();                }                break;        }    }    private void requestLocation() {        //设置定位属性        initLocation();        //开始定位        mlocation.start();    }    private void initLocation() {        LocationClientOption option = new LocationClientOption();        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);        //设置百度坐标        option.setCoorType("bd09ll");        option.setOpenGps(true); // 打开gps        //设置定位延迟        option.setScanSpan(3000);        mlocation.setLocOption(option);    }    @Override    public void onOrientationChanged(float x) {        mXDirection = (int) x;        builder = new MyLocationData.Builder();        builder.accuracy(mCurrentAccracy);        builder.direction(mXDirection);        builder.latitude(mCurrentLantitude);        builder.longitude(mCurrentLongitude);        MyLocationData locationData = builder.build();        mBaiduMap.setMyLocationData(locationData);        // 设置自定义图标        //BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory.fromResource(R.drawable.arrow);        MyLocationConfiguration configuration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, null);        mBaiduMap.setMyLocationConfiguration(configuration);    }    public class MyLocationListener implements BDLocationListener {        @Override        public void onReceiveLocation(BDLocation bdLocation) {            mCurrentAccracy=bdLocation.getRadius();            mCurrentLantitude=bdLocation.getLatitude();            mCurrentLongitude=bdLocation.getLongitude();            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation || bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {                //设置地图显示                navigateTo(bdLocation);            }        }        @Override        public void onConnectHotSpotMessage(String s, int i) {        }    }    private void navigateTo(BDLocation location) {        if (isFirstLocate) {            //定位坐标            LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);            mBaiduMap.animateMapStatus(update);            //设置缩放级别            update = MapStatusUpdateFactory.zoomTo(21f);            mBaiduMap.animateMapStatus(update);            isFirstLocate = false;        }    }    @Override    protected void onResume() {        super.onResume();        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理        mMapView.onResume();        myOrientationListener.start();    }    @Override    protected void onPause() {        super.onPause();        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理        mMapView.onPause();    }    @Override    protected void onStop() {        super.onStop();        myOrientationListener.stop();    }    @Override    protected void onDestroy() {        super.onDestroy();        mlocation.stop();        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理        mMapView.onDestroy();        mBaiduMap.setMyLocationEnabled(false);    }}
public class MyOrientationListener implements SensorEventListener {    private Context context;    private SensorManager sensorManager;    private Sensor accelerometer; // 加速度传感器    private Sensor magnetic; // 地磁场传感器    private float[] accelerometerValues = new float[3];    private float[] magneticFieldValues = new float[3];    private float lastX;    private OnOrientationListener onOrientationListener ;    public MyOrientationListener(Context context)    {        this.context = context;    }    @Override    public void onSensorChanged(SensorEvent event) {        // 接受方向感应器的类型        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {            accelerometerValues = event.values;        }        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {            magneticFieldValues = event.values;        }        getOrientation();    }    public void getOrientation() {        float[] values = new float[3];        float[] R = new float[9];        SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticFieldValues);        //将角度信息计算后返回到values中        SensorManager.getOrientation(R, values);        values[0] = (float) Math.toDegrees(values[0]);        //当方向的改变大于一度时回调监听        if( Math.abs(values[0]- lastX) > 1.0 )        {            onOrientationListener.onOrientationChanged(values[0]);        }        lastX = values[0] ;    }    @Override    public void onAccuracyChanged(Sensor sensor, int accuracy) {    }    public void start(){        // 获得传感器管理器        sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);        if (sensorManager != null)        {            // 初始化加速度传感器            accelerometer = sensorManager                    .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);            // 初始化地磁场传感器            magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);        }        // 注册        if (accelerometer != null || magnetic!=null)        {            sensorManager.registerListener(this,                    accelerometer, Sensor.TYPE_ACCELEROMETER);            sensorManager.registerListener(this, magnetic,                    Sensor.TYPE_MAGNETIC_FIELD);        }    }    public void stop() {        sensorManager.unregisterListener(this);    }    public void setOnOrientationListener(OnOrientationListener onOrientationListener) {        this.onOrientationListener = onOrientationListener;    }    public interface OnOrientationListener{        void onOrientationChanged(float x);    }}
3 0
原创粉丝点击