Android學習——基於百度定位SDK(LBS)實現定位功能

Android學習——基於百度定位SDK(LBS)實現定位功能

最近因爲課程需要,在學習安卓開發的相關課程,需要使用百度定位實現定位功能,因爲小白剛接觸安卓不久,也是爲了幫助一下跟我一樣小白的同學,把相關過程記錄下來,以免忘記。

一、申請百度地圖API_KEY

在這裏插入圖片描述
1.進入百度地圖官網註冊並申請KEY http://lbsyun.baidu.com/
在這裏插入圖片描述
在這裏插入圖片描述
然後點擊創建應用,進行KEY申請,具體看截圖
在這裏插入圖片描述
說明一下,發佈版SHA1、開發版SHA1在安卓程序中都是唯一的識別碼,發佈版SHA1要填寫正確,不然無法獲取相關服務。

想要獲取發佈版SHA1,需要先對程序打包簽名,請自行百度,或參考此文檔 https://blog.csdn.net/l_215851356/article/details/69914213

簽名之後,可以從簽名文件中獲取發佈版SHA1,請自行百度,或參考此文檔 https://jingyan.baidu.com/article/25648fc19932849191fd0001.html

獲取SHA1之後,填入百度申請中,提交,獲取KEY

在這裏插入圖片描述

二、下載百度地圖sdk並導入安卓項目中

在這裏插入圖片描述
選擇需要的sdk,點擊開發包下載(注:本人用迅雷及數個瀏覽器下載,都顯示數據丟失,無法解壓,最後解決辦法是把相關鏈接發到手機,用手機下載後傳到電腦)
在這裏插入圖片描述
解壓後的文件夾
在這裏插入圖片描述
BaiduLBS_android.jar放在project目錄下的app–>libs目錄下,其他目錄放在app–>main–>新建文件夾比如:jniLibs下,請看截圖
在這裏插入圖片描述
在build.gradle中配置libs目錄
在這裏插入圖片描述

sourceSets {
main {
jniLibs.srcDirs = [‘libs’]
}
}

三、配置AndroidManifest.xml

主要爲設置service、引用key以及添加權限
在這裏插入圖片描述

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.shiyan14">

    <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">
        <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>
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="LWSBWe5xkeCPZyNKGrt9f0FMH2TeW91h" />
        <activity android:name=".Activity1"/>
        <activity android:name=".Activity2"/>
    </application>
    <!-- 這個權限用於進行網絡定位-->
    <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>
</manifest>

四、寫上MainActivity功能

我的MainActivity中只寫了兩個按鈕跳轉事件,跳到其他頁面,不要學我的按鈕和類命名方法,要命名得規範一點(因爲命名不規範,沒少挨老師罵)
在這裏插入圖片描述
activity_main.xml我只放了兩個按鈕,跳轉到不同頁面
在這裏插入圖片描述
後面直接放代碼
Activity1

package com.example.shiyan14;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;

public class Activity1 extends AppCompatActivity implements View.OnClickListener {
    private MapView mMapView;
    private BaiduMap mBaiduMap;
    public LocationClient mLocationClient;
    public BDLocationListener myListener = new MyLocationListener();
    private Button bt;
    private Button button;
    private Button buttons;
    private LatLng latLng;
    private boolean isFirstLoc = true; // 是否首次定位

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在使用SDK各組件之前初始化context信息,傳入ApplicationContext
        //注意該方法要再setContentView方法之前實現
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity1);

        initView();
        initMap();
    }

    private void initMap() {
        //獲取地圖控件引用
        mBaiduMap = mMapView.getMap();
        //普通地圖
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        mBaiduMap.setMyLocationEnabled(true);

        //默認顯示普通地圖
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        //開啓交通圖
        //mBaiduMap.setTrafficEnabled(true);
        //開啓熱力圖
        //mBaiduMap.setBaiduHeatMapEnabled(true);
        // 開啓定位圖層
        mBaiduMap.setMyLocationEnabled(true);
        mLocationClient = new LocationClient(getApplicationContext());     //聲明LocationClient類
        //配置定位SDK參數
        initLocation();
        mLocationClient.registerLocationListener(myListener);    //註冊監聽函數
        //開啓定位
        mLocationClient.start();
        //圖片點擊事件,回到定位點
        mLocationClient.requestLocation();
    }

    //配置定位SDK參數
    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy
        );//可選,默認高精度,設置定位模式,高精度,低功耗,僅設備
        option.setCoorType("bd09ll");//可選,默認gcj02,設置返回的定位結果座標系
        int span = 1000;
        option.setScanSpan(span);//可選,默認0,即僅定位一次,設置發起定位請求的間隔需要大於等於1000ms纔是有效的
        option.setIsNeedAddress(true);//可選,設置是否需要地址信息,默認不需要
        option.setOpenGps(true);//可選,默認false,設置是否使用gps
        option.setLocationNotify(true);//可選,默認false,設置是否當GPS有效時按照1S/1次頻率輸出GPS結果
        option.setIsNeedLocationDescribe(true);//可選,默認false,設置是否需要位置語義化結果,可以在BDLocation
        // .getLocationDescribe裏得到,結果類似於「在北京天安門附近」
        option.setIsNeedLocationPoiList(true);//可選,默認false,設置是否需要POI結果,可以在BDLocation.getPoiList裏得到
        option.setIgnoreKillProcess(false);
        option.setOpenGps(true); // 打開gps

        //可選,默認true,定位SDK內部是一個SERVICE,並放到了獨立進程,設置是否在stop的時候殺死這個進程,默認不殺死
        option.SetIgnoreCacheException(false);//可選,默認false,設置是否收集CRASH信息,默認收集
        option.setEnableSimulateGps(false);//可選,默認false,設置是否需要過濾GPS仿真結果,默認需要
        mLocationClient.setLocOption(option);
    }

    //實現BDLocationListener接口,BDLocationListener爲結果監聽接口,異步獲取定位結果
    public class MyLocationListener implements BDLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            //mLocationClient.onReceiveLocation(location);
            latLng = new LatLng(location.getLatitude(), location.getLongitude());
            // 構造定位數據
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    // 此處設置開發者獲取到的方向信息,順時針0-360
                    .direction(100).latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            // 設置定位數據
            mBaiduMap.setMyLocationData(locData);
            // 當不需要定位圖層時關閉定位圖層
            //mBaiduMap.setMyLocationEnabled(false);
            if (isFirstLoc) {
                isFirstLoc = false;
                LatLng ll = new LatLng(location.getLatitude(),
                        location.getLongitude());
                MapStatus.Builder builder = new MapStatus.Builder();
                builder.target(ll).zoom(18.0f);
                mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));

                if (location.getLocType() == BDLocation.TypeGpsLocation) {
                    // GPS定位結果
                    Toast.makeText(Activity1.this, location.getAddrStr(), Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                    // 網絡定位結果
                    Toast.makeText(Activity1.this, location.getAddrStr(), Toast.LENGTH_SHORT).show();

                } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
                    // 離線定位結果
                    Toast.makeText(Activity1.this, location.getAddrStr(), Toast.LENGTH_SHORT).show();

                } else if (location.getLocType() == BDLocation.TypeServerError) {
                    Toast.makeText(Activity1.this, "服務器錯誤,請檢查", Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                    Toast.makeText(Activity1.this, "網絡錯誤,請檢查", Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                    Toast.makeText(Activity1.this, "手機模式錯誤,請檢查是否飛行", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    private void initView() {
        mMapView =  findViewById(R.id.bmapView);
        bt =  findViewById(R.id.bt);
        bt.setOnClickListener(this);
        button =findViewById(R.id.button);
        button.setOnClickListener(this);
        buttons = findViewById(R.id.buttons);
        buttons.setOnClickListener(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命週期管理
        mMapView.onDestroy();
    }

    @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
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt:
                //把定位點再次顯現出來
                MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng);
                mBaiduMap.animateMapStatus(mapStatusUpdate);
                break;
            case R.id.button:
                //衛星地圖
                mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
                break;
            case R.id.buttons:
                //普通地圖
                mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
                break;
        }
    }

}

Activity2主要爲獲取poi
參考了 https://blog.csdn.net/ygreatred/article/details/79872794
使用
location.getLatitude();//緯度
location.getLongitude();//經度
location.getDirection();//定位方向
location.getRadius();//定位精度
location.getCoorType();//定位座標類型
location.getLocType();//定位類型、定位錯誤返回碼
location.getLocTypeDescription();//對應的定位類型說明
location.getTime();//獲取經緯度服務器時間
//判斷用戶是在室內,還是在室外1:室內,0:室外,這個判斷不一定是100%準確的
location.getUserIndoorState();
location.getAddrStr(); //獲取詳細地址信息
location.getCountry(); //獲取國家
location.getProvince(); //獲取省份
location.getCity(); //獲取城市
location.getDistrict(); //獲取區縣
location.getStreet(); //獲取街道信息

public class MyLocationListener extends BDAbstractLocationListener {
    @Override
    public void onReceiveLocation(BDLocation location) {
        //此處的BDLocation爲定位結果信息類,通過它的各種get方法可獲取定位相關的全部結果
        // 以下只列舉部分獲取經緯度相關(常用)的結果信息
        // 更多結果信息獲取說明,請參照類參考中BDLocation類中的說明
        double latitude = location.getLatitude();    //獲取緯度信息
        double longitude = location.getLongitude();    //獲取經度信息
        float radius = location.getRadius();    //獲取定位精度,默認值爲0.0f
        int errorCode = location.getLocType();            //獲取定位類型、定位錯誤返回碼,具體信息可參照類參考中BDLocation類中的說明
        String coorType = location.getCoorType();
        String  s1="緯度:"+String.valueOf(latitude);
        String  s2="經度:"+String.valueOf(longitude);
        String s3="定位精度:"+String.valueOf(radius);
        textView.setText("\n\n" + s1+"\n"+s2+"\n"+s3+"\n"+"詳細地址:"+location.getAddrStr()+"\n"+"國家:"+location.getCountry()+"\n"+"省份:"+location.getProvince()+"\n城市:"+location.getCity()+"\n區縣:"+location.getDistrict()
        +"\n街道信息:"+location.getStreet()+"\n返回碼:"+errorCode+"\n座標類型:"+coorType);
    }
}

activity1.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">

        <Button
            android:id="@+id/bt"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="復位" />

        <Button
            android:id="@+id/button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="衛星" />

        <Button
            android:id="@+id/buttons"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="普通" />
    </LinearLayout>

</RelativeLayout>

activity2.xml

<?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:layout_editor_absoluteY="81dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="332dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

五、運行結果

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
注意:由於代碼中沒有相應的try catch語句或者if語句,如果程序無法獲取權限,可能會出現無法服務或者閃退情況,如果遇到這種情況,請嘗試進入手機設置-更多應用-權限管理,把權限由詢問改爲允許。
或者由手機自帶的安全管家,進入權限管理,把權限由詢問改爲允許。

本人是一枚小白,雖然功能實現了,但代碼中有許多邏輯錯誤,不進行一一優化了。

##最後,需要資源的話,請按照截圖關鍵字搜索(已上傳,審覈過後應該就會放出來了)##

在這裏插入圖片描述