天天看點

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

文章目錄

  • 注冊
  • 申請密鑰
  • 配置
  • 使用
  • 遇到問題

注冊

登入百度地圖開放平台 注冊百度地圖開發者,填寫相關資訊

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

送出成功後收到郵件

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

點選連結彈出如下提示就算激活成功了

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

申請密鑰

點選申請密鑰或者建立應用

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

填入應用相關資訊

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
  • Android Studio擷取SHA1方式
  1. release

    在底部Terminal控制台(沒有這欄,在頂部View->Tool Windows選上或者AIt+F12)中,輸入:keytool -list -keystore -v -keystore + .jks檔案的絕對路徑

    keytool -list -v -keystore C:\keystore.jks
               
    我的jks就在項目底下是以直接輸入keystore.jks
    Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
    然後輸入密鑰庫密碼(沒印象有這東西的試試看直接回車),就成功擷取我們需要的SHA1
    Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
  2. debug

    如果知道debug.keystore的路徑,就和release的方式一樣擷取。

    還可以通過點選右側Gradle(沒有這欄,在頂部View->Tool Windows選上)->appName->Tasks->android->signingReport

    Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
    等待片刻就可以在Run一欄看到我們要的debug的SAH1了
    Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
    申請密鑰時最好把釋出版和開發版的SHA1都填上,友善我們調試。
  • 包名擷取

    build.gradle的applicationId或者AndroidManifest的package

    Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
    Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
    注意:使用Android Studio開發,如遇到applicationId 與在 AndroidManifest.xml 中定義的包名不一緻的情況,以appclicationid為準。

送出成功就可以在檢視應用中看到我們的應用資訊

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

配置

前往百度地圖SDK下載下傳所需的sdk,因為我們隻需要擷取定位資訊,是以下載下傳基礎定位的就夠了

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題
Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

将我們下載下傳的基礎定位包解壓後,将裡面的東西拷貝一份到libs檔案夾中,如果沒有可以建立一個。

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

然後在gradle配置我們的libs路徑(sourceSets和defaultConfig同級)

sourceSets{
        main{
            //說明so的路徑為該libs路徑
            jniLibs.srcDir 'libs'
        }
    }
           

注意這邊的libs是和src同級,才會生效,不同目錄結構按以下修改

jniLibs.srcDirs =['src/main/libs']
           

然後在build.gradle添加依賴

dependencies{
  api files('libs/BaiduLBS_Android.jar')
}
           

或者通過頂部File->Project Sturcture(Ctrl+Alt+Shift+S)打開視窗,根據圖示選擇需要的jar包,會自動引入上方代碼,最後同步一下gradle。

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

如果需要混淆的,在proguard-rules.pro加入以下代碼

-keep class com.baidu.** {*;}
-keep class mapsdkvi.com.** {*;}
-dontwarn com.baidu.**
           

使用

在AndoirdMainifest.xml的application底下添加

<!-- 聲明service元件 -->
<service
    android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote"></service>

<!-- AK鑒權 -->
<!-- meta-data需要寫在application中 -->
<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="申請的密鑰AK" /> 
           

加入所需的權限

<!-- 這個權限用于進行網絡定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 這個權限用于通路GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 用于通路wifi網絡資訊,wifi資訊會用于進行網絡定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- 擷取營運商資訊,用于支援提供營運商資訊相關的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 這個權限用于擷取wifi的擷取權限,wifi資訊會用來進行網絡定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- 用于讀取手機目前的狀态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- 寫入擴充存儲,向擴充卡寫入資料,用于寫入離線定位資料-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 通路網絡,網絡定位需要上網-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD卡讀取權限,使用者寫入離線定位資料-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
           

擷取定位資訊我用了官方demo中的LocationService(最後會附上代碼),在需要的activity初始化中加入

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_location);
    locationService = new LocationService(this);
    locationService.registerListener(mListener);
    locationService.setLocationOption(locationService.getDefaultLocationClientOption());
}
           
  • 初始化location執行個體
    locationService = new LocationService(this);
               
    如果是多個activity中使用建議在Application中初始化location執行個體,建立一個App類
    public class App extends Application {
        public LocationService locationService;
    
        @Override
        public void onCreate() {
            super.onCreate();
            locationService = new LocationService(this);
        }
    }
               
    在AndoirdMainifest.xml的application加上name屬性
    <application
            android:name=".App">
    </application>
               
    然後在我們要用的activity中擷取Application中的執行個體
    locationService = ((App) getApplication()).locationService;
               
  • 注冊定位服務
    locationService.registerListener(mListener);
               
    mListener為我們定位後的回調結果
    /*****
    *
    * 定位結果回調,重寫onReceiveLocation方法
    *
    */
    private BDAbstractLocationListener mListener = new BDAbstractLocationListener() {
    
       @Override
       public void onReceiveLocation(BDLocation location) {
           // TODO Auto-generated method stub
           if (null != location && location.getLocType() != BDLocation.TypeServerError) {
           		//擷取資訊後的操作
           }
       }
    };
               
  • 設定配置
    locationService.setLocationOption(locationService.getDefaultLocationClientOption());
               
    目前我使用的是demo中的預設配置,可按自己的要求修改
    //預設Option設定 
    public LocationClientOption getDefaultLocationClientOption(){
    	if(mOption == null){
    		mOption = new LocationClientOption();
    		mOption.setLocationMode(LocationMode.Hight_Accuracy);//可選,預設高精度,設定定位模式,高精度,低功耗,僅裝置
    		mOption.setCoorType("bd09ll");//可選,預設gcj02,設定傳回的定位結果坐标系,如果配合百度地圖使用,建議設定為bd09ll;
    		mOption.setScanSpan(3000);//可選,預設0,即僅定位一次,設定發起連續定位請求的間隔需要大于等于1000ms才是有效的
    	    mOption.setIsNeedAddress(true);//可選,設定是否需要位址資訊,預設不需要
    	    mOption.setIsNeedLocationDescribe(true);//可選,設定是否需要位址描述
    	    mOption.setNeedDeviceDirect(false);//可選,設定是否需要裝置方向結果
    	    mOption.setLocationNotify(false);//可選,預設false,設定是否當gps有效時按照1S1次頻率輸出GPS結果
    	    mOption.setIgnoreKillProcess(true);//可選,預設true,定位SDK内部是一個SERVICE,并放到了獨立程序,設定是否在stop的時候殺死這個程序,預設不殺死   
    	    mOption.setIsNeedLocationDescribe(true);//可選,預設false,設定是否需要位置語義化結果,可以在BDLocation.getLocationDescribe裡得到,結果類似于“在北京天安門附近”
    	    mOption.setIsNeedLocationPoiList(true);//可選,預設false,設定是否需要POI結果,可以在BDLocation.getPoiList裡得到
    	    mOption.SetIgnoreCacheException(false);//可選,預設false,設定是否收集CRASH資訊,預設收集
    		mOption.setOpenGps(true);//可選,預設false,設定是否開啟Gps定位
    	    mOption.setIsNeedAltitude(false);//可選,預設false,設定定位時是否需要海拔資訊,預設不需要,除基礎定位版本都可用
    	}
    	return mOption;
    }
               

初始化以及注冊執行個體後我們就可以使用了,在要定位的啟動

//啟動
locationService.start();
           

停止定位

//停止
locationService.stop();
           

當然不要忘了在銷毀頁面登出監聽

@Override
    protected void onDestroy() {
        super.onDestroy();
        locationService.unregisterListener(mListener); //登出掉監聽
        locationService.stop(); //停止定位服務
    }
           

效果圖如下

Android使用百度地圖api擷取定位資訊(經緯度)注冊 申請密鑰配置使用遇到問題

最後附上代碼

LocationService.class

import android.content.Context;
import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode;

public class LocationService {
	private LocationClient client = null;
	private LocationClientOption mOption,DIYoption;
	private Object objLock = new Object();

	public LocationService(Context locationContext){
		synchronized (objLock) {
			if(client == null){
				client = new LocationClient(locationContext);
				client.setLocOption(getDefaultLocationClientOption());
			}
		}
	}
	
	// 注冊
	public boolean registerListener(BDAbstractLocationListener listener){
		boolean isSuccess = false;
		if(listener != null){
			client.registerLocationListener(listener);
			isSuccess = true;
		}
		return  isSuccess;
	}
	
	// 登出
	public void unregisterListener(BDAbstractLocationListener listener){
		if(listener != null){
			client.unRegisterLocationListener(listener);
		}
	}
	
	//設定配置
	public boolean setLocationOption(LocationClientOption option){
		boolean isSuccess = false;
		if(option != null){
			if(client.isStarted())
				client.stop();
			DIYoption = option;
			client.setLocOption(option);
		}
		return isSuccess;
	}

	//預設Option設定 
	public LocationClientOption getDefaultLocationClientOption(){
		if(mOption == null){
			mOption = new LocationClientOption();
			mOption.setLocationMode(LocationMode.Hight_Accuracy);//可選,預設高精度,設定定位模式,高精度,低功耗,僅裝置
			mOption.setCoorType("bd09ll");//可選,預設gcj02,設定傳回的定位結果坐标系,如果配合百度地圖使用,建議設定為bd09ll;
			mOption.setScanSpan(3000);//可選,預設0,即僅定位一次,設定發起連續定位請求的間隔需要大于等于1000ms才是有效的
		    mOption.setIsNeedAddress(true);//可選,設定是否需要位址資訊,預設不需要
		    mOption.setIsNeedLocationDescribe(true);//可選,設定是否需要位址描述
		    mOption.setNeedDeviceDirect(false);//可選,設定是否需要裝置方向結果
		    mOption.setLocationNotify(false);//可選,預設false,設定是否當gps有效時按照1S1次頻率輸出GPS結果
		    mOption.setIgnoreKillProcess(true);//可選,預設true,定位SDK内部是一個SERVICE,并放到了獨立程序,設定是否在stop的時候殺死這個程序,預設不殺死   
		    mOption.setIsNeedLocationDescribe(true);//可選,預設false,設定是否需要位置語義化結果,可以在BDLocation.getLocationDescribe裡得到,結果類似于“在北京天安門附近”
		    mOption.setIsNeedLocationPoiList(true);//可選,預設false,設定是否需要POI結果,可以在BDLocation.getPoiList裡得到
		    mOption.SetIgnoreCacheException(false);//可選,預設false,設定是否收集CRASH資訊,預設收集
			mOption.setOpenGps(true);//可選,預設false,設定是否開啟Gps定位
		    mOption.setIsNeedAltitude(false);//可選,預設false,設定定位時是否需要海拔資訊,預設不需要,除基礎定位版本都可用
		 
		}
		return mOption;
	}


	//自定義Option設定
	public LocationClientOption getOption(){
		if(DIYoption == null) {
			DIYoption = new LocationClientOption();
		}
		return DIYoption;
	}

	public void start(){
		synchronized (objLock) {
			if(client != null && !client.isStarted()){
				client.start();
			}
		}
	}
	public void stop(){
		synchronized (objLock) {
			if(client != null && client.isStarted()){
				client.stop();
			}
		}
	}

	public boolean isStart() {
		return client.isStarted();
	}

	public boolean requestHotSpotState(){
		return client.requestHotSpotState();
	}
}
           

LocationActivity.class

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.Poi;
import com.ffcs.imr.service.LocationService;

public class LocationActivity extends Activity {
    private LocationService locationService;
    private TextView mTextView;
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);

        mTextView = findViewById(R.id.textview);
        button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (button.getText().toString().equals("打開定位")) {
                    locationService.start();
                } else {
                    locationService.stop();
                    button.setText("打開定位");
                    mTextView.setText("");
                }
            }
        });

        locationService = new LocationService(this);
//        多個activity
//        locationService = ((App) getApplication()).locationService;
        locationService.registerListener(mListener);
        locationService.setLocationOption(locationService.getDefaultLocationClientOption());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        locationService.unregisterListener(mListener); //登出掉監聽
        locationService.stop(); //停止定位服務
    }

    /*****
     *
     * 定位結果回調,重寫onReceiveLocation方法,可以直接拷貝如下代碼到自己工程中修改
     *
     */
    private BDAbstractLocationListener mListener = new BDAbstractLocationListener() {

        @Override
        public void onReceiveLocation(BDLocation location) {
            // TODO Auto-generated method stub
            if (null != location && location.getLocType() != BDLocation.TypeServerError) {
                button.setText("停止定位");
                StringBuilder sb = new StringBuilder(256);
                sb.append("time : ");
                /**
                 * 時間也可以使用systemClock.elapsedRealtime()方法 擷取的是自從開機以來,每次回調的時間;
                 * location.getTime() 是指服務端出本次結果的時間,如果位置不發生變化,則時間不變
                 */
                sb.append(location.getTime());
                sb.append("\nlocType : ");// 定位類型
                sb.append(location.getLocType());
                sb.append("\nlocType description : ");// *****對應的定位類型說明*****
                sb.append(location.getLocTypeDescription());
                sb.append("\nlatitude : ");// 緯度
                sb.append(location.getLatitude());
                sb.append("\nlontitude : ");// 經度
                sb.append(location.getLongitude());
                sb.append("\nradius : ");// 半徑
                sb.append(location.getRadius());
                sb.append("\nCountryCode : ");// 國家碼
                sb.append(location.getCountryCode());
                sb.append("\nCountry : ");// 國家名稱
                sb.append(location.getCountry());
                sb.append("\ncitycode : ");// 城市編碼
                sb.append(location.getCityCode());
                sb.append("\ncity : ");// 城市
                sb.append(location.getCity());
                sb.append("\nDistrict : ");// 區
                sb.append(location.getDistrict());
                sb.append("\nStreet : ");// 街道
                sb.append(location.getStreet());
                sb.append("\naddr : ");// 位址資訊
                sb.append(location.getAddrStr());
                sb.append("\nUserIndoorState: ");// *****傳回使用者室内外判斷結果*****
                sb.append(location.getUserIndoorState());
                sb.append("\nDirection(not all devices have value): ");
                sb.append(location.getDirection());// 方向
                sb.append("\nlocationdescribe: ");
                sb.append(location.getLocationDescribe());// 位置語義化資訊
                sb.append("\nPoi: ");// POI資訊
                if (location.getPoiList() != null && !location.getPoiList().isEmpty()) {
                    for (int i = 0; i < location.getPoiList().size(); i++) {
                        Poi poi = (Poi) location.getPoiList().get(i);
                        sb.append(poi.getName() + ";");
                    }
                }
                if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位結果
                    sb.append("\nspeed : ");
                    sb.append(location.getSpeed());// 速度 機關:km/h
                    sb.append("\nsatellite : ");
                    sb.append(location.getSatelliteNumber());// 衛星數目
                    sb.append("\nheight : ");
                    sb.append(location.getAltitude());// 海拔高度 機關:米
                    sb.append("\ngps status : ");
                    sb.append(location.getGpsAccuracyStatus());// *****gps品質判斷*****
                    sb.append("\ndescribe : ");
                    sb.append("gps定位成功");
                } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 網絡定位結果
                    // 營運商資訊
                    if (location.hasAltitude()) {// *****如果有海拔高度*****
                        sb.append("\nheight : ");
                        sb.append(location.getAltitude());// 機關:米
                    }
                    sb.append("\noperationers : ");// 營運商資訊
                    sb.append(location.getOperators());
                    sb.append("\ndescribe : ");
                    sb.append("網絡定位成功");
                } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 離線定位結果
                    sb.append("\ndescribe : ");
                    sb.append("離線定位成功,離線定位結果也是有效的");
                } else if (location.getLocType() == BDLocation.TypeServerError) {
                    sb.append("\ndescribe : ");
                    sb.append("服務端網絡定位失敗,可以回報IMEI号和大體定位時間到[email protected],會有人追查原因");
                } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                    sb.append("\ndescribe : ");
                    sb.append("網絡不同導緻定位失敗,請檢查網絡是否通暢");
                } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                    sb.append("\ndescribe : ");
                    sb.append("無法擷取有效定位依據導緻定位失敗,一般是由于手機的原因,處于飛行模式下一般會造成這種結果,可以試着重新開機手機");
                }
                logMsg(sb.toString());
            }
        }

    };

    /**
     * 顯示請求字元串
     */
    public void logMsg(final String str) {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mTextView.post(new Runnable() {
                        @Override
                        public void run() {
                            mTextView.setText(str);
                        }
                    });
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
           

activity_location.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">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="打開定位" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@+id/button" />
</android.support.constraint.ConstraintLayout>
           

遇到問題

  1. NetWork location failed because baidu location service can not decrypt the request query, please check the so file!

    a. 確定自己的so檔案沒有少

    b. 在檢查下build.gradle的lib配置是否正确,詳細内容請看本文的配置 。

  2. NetWork location failed because baidu location service check the key is unlegal, please check the key in AndroidManifest.xml!

    a. 先檢查AndroidManifest.xml是否配置了AK

    b. 看看申請的包名和所用的AK是否比對

    c. 注意下自己申請的時候用的SHA1是哪個版本的,如果你直接運作AndroidStudio的debug版本,要確定有在申請的時候填入相應的SHA1。打包路徑的簽名隻能讓你release版本使用定位功能。debug版本的簽名擷取請看本文的申請密鑰 。

  3. Offline location failed, please check the net (wifi/cell)!

    a. 檢查網路是否打開

    b. 是否在AndroidManifest.xml加入網絡權限

    c. 是否賦予應用網絡權限,權限的選擇看本文的使用

  4. Location failed beacuse we can not get any loc information!

    a. 是否在AndroidManifest.xml加入定位權限

    b. 是否賦予應用定位權限,權限的選擇看本文的使用

    • 無法擷取定位資訊定位
    • 成功定位一次後,接下來無法擷取定位資訊
    • 回調BDAbstractLocationListener沒有執行

檢查錯誤3是否發生,再确認AndoirdMainifest.xml的application有沒有加上

<!-- 聲明service元件 -->
<service
    android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote"></service>

<!-- AK鑒權 -->
<!-- meta-data需要寫在application中 -->
<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="申請的密鑰AK" />