第一行代码第二版(郭霖著)笔记之第十一章(百度地图)

1. 基于位置的服务简介

  • GPS定位:基于手机内置的GPS硬件直接和卫星交互来后去当前的经纬度信息,这种定格为i方式精确度非常高,但缺点是只能在室外使用,室内基本无法接收到卫星的信号。
  • 网络定位:根据手机当前网络附近的三个基站进行测速,以此计算出手机和每个基站之间的距离,在通过三角定位确定出一个大概的位置,这种定位方式精确度一般,但优点是在室内室外都可以使用。
  • 在国内Google的网路服务不可用,所以网络定位的API失效。为了在室内和室外都可以成功定位,这里采用百度SDK来进行开发操作。

2. 获取发布版SHA1:

  • 在cmd中输入命令,然后输入密码即可:
    keytool -list -v -keystore <签名文件路径>

3. 确定自己位置的经纬度

  • 布局:
<TextView
    android:id="@+id/position_text_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:text="经纬度是多少"
    android:textSize="25dp"
    android:visibility="gone" />
  • 配置文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fkq.baidumaps">


    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="6bnAKCzjTlK27e4Wl5UBQRqQGslWoV34"></meta-data>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote"></service>
    </application>

</manifest>

说明:
1. 添加了多种权限。
2. 添加了meta-data标签,注明APIKEY.
3. 注册一个LBS SDK的服务。
  • MainActivity:
public class MainActivity extends AppCompatActivity {

    public LocationClient mLocationClient;

    private TextView positionText;

    private StringBuilder currentPosition;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(new MyLocationListener());
        setContentView(R.layout.activity_main);
        positionText = (TextView) findViewById(R.id.position_text_view);
        List<String> 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();
        }
    }

    private void requestLocation() {
        initLocation();
        mLocationClient.start();
    }

    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);
        mLocationClient.setLocOption(option);
    }

    @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(this, "必须同意所有权限才能使用本程序", Toast.LENGTH_SHORT).show();
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                } else {
                    Toast.makeText(this, "发生未知错误", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
        }
    }


    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {

            currentPosition = new StringBuilder();
            currentPosition.append("纬度:").append(location.getLatitude()).append("\n");
            currentPosition.append("经度:").append(location.getLongitude()).append("\n");
            currentPosition.append("定位方式:");
            if (location.getLocType() == BDLocation.TypeGpsLocation) {
                currentPosition.append("GPS");
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                currentPosition.append("网络");
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    positionText.setText(currentPosition);
                }
            });
        }

        @Override
        public void onConnectHotSpotMessage(String s, int i) {

        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
    }
}

说明:
1. onCreate方法中创建LocationClient实例,接收一个全局的上下文参数。接着实例会注册一个监听器,当获取位置信息的时候,回调这个定位监听器。
2. 运行时权限采用集合的方式,如果没有授权便添加权限到集合中,然后将List转化为数组,再调用ActivityCompat.requestPermissions方法一次性申请。onRequestPermissionsResult方法循环每个权限,如果有一个权限被拒绝,直接调用finish方法关闭当前程序,只有所有的权限被用户同意,才会调用requestLocation方法进行地理位置的定位。
3. mLocationClient.start()方法进行定位,回调监听器:BDLocation.getLatitude获取位置的纬度,getLongitude获取位置的经度,getLocType获取定位方式。
4. 默认情况下定位mLocationClient.start()方法只会执行一次。增加 initLocation()方法,在方法中创建LocationClientOption对象,然后调用它的setScanSpan方法设置更新的间隔,传入5000,表示5秒钟会更新一下当前的位置,意味着监听器跟随5秒设置页面的经纬度。
5.活动被销毁的时候调用mLocationClient.stop()方法停止定位。

4. 选择定位模式

  • 手机定位三种模式:高精度定位、节电、仅限设备。高精度定位允许使用GPS、无线网络、蓝牙或移动网络进行定位,节电模式表示仅使用网络定位,仅限设备模式表示仅使用GPS定位。不用担心开启了GPS定位,耗费电量,因为只有定位的时候才会消耗电量。
  • initLocation方法(百度LBS)中对定位模式进行了指定:Hight_Accuracy、Battery_Saving和Device_Sensors。分别对应手机定位的三种模式。
  • 我们这里设定为高精度模式(第一行代码为设备模式):
private void initLocation() {
    LocationClientOption option = new LocationClientOption();
    option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
    mLocationClient.setLocOption(option);
}

说明:不管是在屋里还是屋外都可以对位置进行定位。

5. 显示看得懂的定位信息

  • 在initLocation()方法添加如下代码:
option.setIsNeedAddress(true);
说明:表示我们需要获取详细的地理信息
  • 在onReceiveLocation方法中获取省市区街道等信息
currentPosition.append("国家:").append(location.getCountry()).append("\n");
currentPosition.append("省:").append(location.getProvince()).append("\n");
currentPosition.append("市:").append(location.getCity()).append("\n");
currentPosition.append("区:").append(location.getDistrict()).append("\n");
currentPosition.append("街道:").append(location.getStreet()).append("\n");

注意:如果定位方式指定为设备,但是获取具体信息这一功能,还是会自动开启网络定位。

6. 显示百度地图

  • 布局:
    <com.baidu.mapapi.map.MapView
        android:id="@+id/bmapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true" />

说明: 自定义的MapView控件,用来显示地图。
  • MainActivity添加代码:
onCreate方法中:
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.bmapView);

 @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
        mapView.onDestroy();
    }

说明:
1. SDKInitializer调用initialize方法,传入全局的上下文进行初始化操作,地图就会显示出来了,一句代码!
2. 通过findViewById方法获取到了MapView实例。
3. 在onResume、onPause和onDestroy方法中对MapView生命周期进行管理,以免浪费资源。

7. 移动到我的位置

  • 获取地图的总控制器BaiduMap类的实例。
BadiuMap baiduMap = mapView.getMap();

说明:有了BiaduMap类的实例,就可以对地图进行各种各样的操作,比如设置地图的缩放级别以及将地图移动到某一个经纬度上。
  • 百度地图可以将缩放级别的取值范围定在3到19之间,值越大,地图越精细。
MapStatusUpdate update = MapStatusUpdateFactory.zoomTo(16f);
baiduMap.animateMapStatus(update);
  • 借助LatLng类实现地图移动到某一个经纬度上
LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
baiduMap.animateMapStatus(update);

8. 让“我”显示在地图上

  • 取消百度地图让”我”显示在地图上的限制
baiduMap.setMyLocationEnabled(true);
  • 借助MyLocationData.Builder类封装经纬度信息
MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
  • 借助MyLocationData.Builder类的build方法,让设备的位置显示在地图上
MyLocationData locationdata = locationBuilder.build();
    baiduMap.setMyLocationData(locationdata);
  • 程序退出的时候,关闭我的位置显示功能
baiduMap.setMyLocationEnabled(false);

9. 附上MainActivity的代码

public class MainActivity extends AppCompatActivity {

    public LocationClient mLocationClient;

    private TextView positionText;

    private StringBuilder currentPosition;

    private MapView mapView;

    private BaiduMap baiduMap;

    private boolean isFirstLocate = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(new MyLocationListener());
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);
        positionText = (TextView) findViewById(R.id.position_text_view);
        mapView = (MapView) findViewById(R.id.bmapView);
        baiduMap = mapView.getMap();
        baiduMap.setMyLocationEnabled(true);
        List<String> 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();
        }
    }

    private void requestLocation() {
        initLocation();
        mLocationClient.start();
    }

    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        option.setScanSpan(5000);
        option.setIsNeedAddress(true);
        mLocationClient.setLocOption(option);
    }

    @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(this, "必须同意所有权限才能使用本程序", Toast.LENGTH_SHORT).show();
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                } else {
                    Toast.makeText(this, "发生未知错误", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
        }
    }

    private void navigateTo(BDLocation location) {
        if (isFirstLocate) {
            LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(update);
            update = MapStatusUpdateFactory.zoomTo(16f);
            baiduMap.animateMapStatus(update);
            isFirstLocate = false;
        }
        MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
        MyLocationData locationdata = locationBuilder.build();
        baiduMap.setMyLocationData(locationdata);
    }

    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            if (location.getLocType() == BDLocation.TypeGpsLocation || location.getLocType() == BDLocation.TypeNetWorkLocation) {
                navigateTo(location);
            }
            currentPosition = new StringBuilder();
            currentPosition.append("纬度:").append(location.getLatitude()).append("\n");
            currentPosition.append("经度:").append(location.getLongitude()).append("\n");
            currentPosition.append("国家:").append(location.getCountry()).append("\n");
            currentPosition.append("省:").append(location.getProvince()).append("\n");
            currentPosition.append("市:").append(location.getCity()).append("\n");
            currentPosition.append("区:").append(location.getDistrict()).append("\n");
            currentPosition.append("街道:").append(location.getStreet()).append("\n");
            currentPosition.append("定位方式:");
            if (location.getLocType() == BDLocation.TypeGpsLocation) {
                currentPosition.append("GPS");
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                currentPosition.append("网络");
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    positionText.setText(currentPosition);
                }
            });
        }

        @Override
        public void onConnectHotSpotMessage(String s, int i) {

        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
        mapView.onDestroy();
        baiduMap.setMyLocationEnabled(false);
    }
}
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值