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開發(四)一定會找機會把內容完善的!

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