Android Studio开发(五)使用百度地图API实现实时定位

Android Studio开发(五)使用百度地图API实现实时定位

一、任务需求

  • 阅读百度地图开发者文档,进行基于百度地图的简单应用开发。
  • 需要实现的基本功能:实时定位,在地图上标记出使用者所在的位置。

二、安卓基于位置的服务(Location Based Service, LBS)

1. LBS定义

位置服务(Location Based Services,LBS)又称定位服务,是指通过GPS卫星或者网络(WiFi或GPRS)获取各种终端的地理座标(经度和纬度),在电子地图平台的支撑下,为用户提供基于位置导航、查询的一种信息服务。
目前,使用LBS服务的应用涉及到了我们生活的方方面面,诸如美团、饿了么、各类地图app,各类运动app以及最近的战疫健康打卡等,学会使用LBS还是有很大帮助的。

2. 三种常见的定位模式

目前,常见的三种定位模式为:

  • GPS定位
  • Wi-Fi定位
  • 基站定位

接下来,我来做一个关于这三种定位模式的简单梳理。

2.1 GPS定位

全球定位系统(Global Positioning System,GPS)是一种以人造地球卫星为基础的高精度无线电导航的定位系统,它在全球任何地方以及近地空间都能够提供准确的地理位置、车行速度及精确的时间信息。概括地说,利用手机gps硬件定位,实现简单,手机本地就能实现定位,不需要和服务端进行交互。

//伪代码
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, listener);

然而,使用GPS定位具有一定的局限性。当使用者处在桥梁下、大树下、建筑物内、隧道内时,手机很多时候都无法接收到GPS信号,这时GPS定位服务将无法使用,或者说信号极度微弱。

在室内无法定位是gps定位的最大问题,此时就得利用WiFi定位了。

2.2 Wi-Fi定位

看名字可能很多人觉得奇怪,Wi-Fi怎么能知道我的位置呢,难道Wi-Fi硬件会返回位置吗?其实这些Wi-Fi都不能做到。
Wi-Fi定位的原理是,我们在室外的时候,手机能接收到gps位置信息,也能扫描到WiFi,当手机把gps位置和WiFi传到后端服务器,WiFi和gps位置就建立了映射关系,当手机在室内无法接收到gps时,却能扫描WiFi,手机把WiFi传到服务器查询出对应的gps位置,然后进行计算可以得到位置结果(经纬度),其中映射和计算是很复杂的过程,感兴趣的同学可以查阅相关资料。wifi定位需要wifi开启,并且手机能上网。

2.3 基站定位

当手机无法扫描到WiFi时,只要装了sim卡,就能连接移动或联通等基站,即可用基站定位,定位原理和WiFi大致相同。基站定位需要装了sim卡,并且手机能上网。

wifi定位基站定位统称为网络定位,当wifi关闭,或者扫描不到WiFi列表时,sdk只会把获取的基站信息发给服务端,进行基站定位;如果没有sim,wifi开启,则sdk会把扫描到的WiFi信息发给服务端,进行wifi定位;如果既有wifi又有基站,则sdk会把这两者信息都发给服务端,具体用哪一种定位,不太确定,但绝大多数情况下都是用wifi定位的。

在室内无gps时,百度定位就是利用的WiFi和基站定位的,在室外有gps时,百度是利用的android自带的LocationManager进行定位,当然室外也可以用WiFi基站定位。

2.4 三种定位方式总结

定位方式 总结
gps定位 精度很高,几米到十几米,但是耗电严重
WiFi定位 精度相对于gps差一点,但是也能到十几米、几十米,也有上百米的误差的,低耗电
基站定位 精度很差,一般都有几百米,上千米的误差

这个误差其实和wifi、基站的信号覆盖半径有关,wifi覆盖半径大概100m左右,而基站的覆盖半径就到km级别了。

三、使用百度地图API进行简单定位

1. 获取SDK

  1. 申请开发者账户
  2. 创建应用,这里简单地给大家个教程:
    步骤一
    官方给出的获取SHA1的方法稍微不小心容易出错(项目包名称的方法可以参考),这里给出一个更简易的方法,在需要使用SDK的项目中,打开Gradle,app-->Tasks-->android-->signingReport,双击后即可在控制台看到SHA1代码了。
    SHA1寻找
    信息填写完确认提交后,即可得到对应的AK(API Key),即我们需要的SDK。
    (注意,AK和项目一一对应,不能一对多使用)

2. 配置百度地图API

  1. 下载所需对应功能的jar包资源
  2. 将下载的压缩包文件解压至app目录下的lib文件夹中
  3. app目录下的build.gradle文件中android块中配置sourceSets标签,如果没有使用该标签则新增,详细配置代码如下:
sourceSets {
           main {
               jniLibs.srcDir 'libs'
           }
}

记得重新编译gradle,不然下面一步的service会找不到com.baidu.location.f,然后飘红
5. 在AndroidManifest.xml文件中进行相关配置:

  • 在application标签下添加如下代码
<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="你申请到的AK"/>
<service android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote"/>
  • 声明权限
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 这个权限用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_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" />
<!-- SD卡读取权限,用户写入离线定位数据-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>

3. 编码阶段

这里其实百度地图的Android定位开发文档有着较好的说明示例,主要参照开发文档即可实现简单的定位功能了。
这里展示部分代码如下:

 private void requestLocation() {
        MyLocationListener myLocationListener = new MyLocationListener();
        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(myLocationListener);
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);

        mapView = findViewById(R.id.bmapView);
        baiduMap = mapView.getMap();
        baiduMap.setMyLocationEnabled(true);
        txtPosition = findViewById(R.id.txtPosition);

        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(1000);//每一秒发送一次
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        option.setIsNeedAddress(true);
        mLocationClient.setLocOption(option);
        mLocationClient.start();//启动位置请求
    }


    private class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            StringBuffer currentPosition = new StringBuffer();
            currentPosition.append("Longitude: ").append(bdLocation.getLongitude()).append("\n");
            currentPosition.append("Latitude: ").append(bdLocation.getLatitude());
            String s = "" + bdLocation.getLatitude();
            txtPosition.setText(currentPosition);

            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation || bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {
                setMyLocation(bdLocation);
            }

        }
    }

    private void setMyLocation(BDLocation bdLocation) {
        if (isFirstLocation) {
            LatLng latLng = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(latLng);
            MyLocationData locationData = new MyLocationData.Builder().latitude(latLng.latitude).longitude(latLng.longitude).build();
            baiduMap.animateMapStatus(update);
            baiduMap.setMyLocationData(locationData);       // 地图上显示定位点
            isFirstLocation = false;
        }
    }

四、实现效果

这里需要说明,由于我本人没有安卓设备,在模拟器上运行无法获取实际地理座标(之后借来了别人的安卓设备进行调试,定位成功)。感兴趣且有条件的读者可以下载下来这个小项目进行真机测试,本次项目对应源码附在文末。
定位展示

本次项目对应源码
p.s.: 最近临近期末太忙了,上次的AS开发(四)一定会找机会把内容完善的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章