首先進(jìn)入百度地圖開發(fā)者中心,找到鷹眼軌跡。按照開發(fā)指南首先申請(qǐng)密鑰,即獲取百度要求的sha1值,在Android studio控制臺(tái)G:\android2016\LBSdemo>下輸入keytool -list -v -keystore D:\key\lbsdemo.jks提示'keytool' 不是內(nèi)部或外部命令,也不是可運(yùn)行的程序。可能是我打開方式不對(duì),于是我到命令行窗口在Java的安裝目錄下找到keytool命令,Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

  那么按照提示輸入
Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

其中命令-keystore后的目錄是Android Studio在打包時(shí)開發(fā)者設(shè)置的key的路徑,接著會(huì)讓你輸入當(dāng)時(shí)設(shè)置的密碼,密碼輸入時(shí)不顯示,回車即可。http://lbsyun.baidu.com/index.php?title=android-yingyan/guide/key此處有官方圖文引導(dǎo)。

  下一步配置工程,下載庫文件解壓后將庫粘到libs文件夾下,并在app的build gradle 添加

sourceSets {
        main {
            jniLibs.srcDir 'libs'
        }
    }

  接下來配置清單文件:(直接從官網(wǎng)上粘)

1、在Application標(biāo)簽中聲明SERVICE組件,每個(gè)APP擁有自己獨(dú)立的鷹眼追蹤service

<service 
          android:name="com.baidu.trace.LBSTraceService" 
          android:enabled="true"
          android:process=":remote"> 
</service>

2、聲明使用權(quán)限:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

<!-- 這個(gè)權(quán)限用于進(jìn)行網(wǎng)絡(luò)定位--> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> 
<!-- 這個(gè)權(quán)限用于訪問GPS定位--> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> 
<!-- 用于訪問wifi網(wǎng)絡(luò)信息,wifi信息會(huì)用于進(jìn)行網(wǎng)絡(luò)定位-->
 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> 
<!-- 獲取運(yùn)營商信息,用于支持提供運(yùn)營商信息相關(guān)的接口--> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> 
<!-- 這個(gè)權(quán)限用于獲取wifi的獲取權(quán)限,wifi信息會(huì)用來進(jìn)行網(wǎng)絡(luò)定位-->
 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
 <!-- 用于讀取手機(jī)當(dāng)前的狀態(tài)--> 
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> 
<!-- 寫入擴(kuò)展存儲(chǔ),向擴(kuò)展卡寫入數(shù)據(jù),用于寫入對(duì)象存儲(chǔ)BOS數(shù)據(jù)--> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
 <!-- 訪問網(wǎng)絡(luò),網(wǎng)絡(luò)定位需要上網(wǎng)-->
 <uses-permission android:name="android.permission.INTERNET" /> 
<!-- SD卡讀取權(quán)限,用于寫入對(duì)象存儲(chǔ)BOS數(shù)據(jù)-->
 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<!-- 用于加快GPS首次定位-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
<!-- 用于Android M及以上系統(tǒng),申請(qǐng)加入忽略電池優(yōu)化白名單-->
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"></uses-permission>

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

在Mainfest.xml正確設(shè)置AccessKey(ak),如果設(shè)置錯(cuò)誤將會(huì)導(dǎo)致鷹眼服務(wù)無法正常使用。需在Application標(biāo)簽中加入以下代碼,并填入開發(fā)者自己的 Android 類型 ak。meta-data與activity同一級(jí)。

AK就是剛剛拿SHA1申請(qǐng)的那個(gè)字符串。

<meta-data             
android:name="com.baidu.lbsapi.API_KEY"             android:value="AK" />       //key:開發(fā)者申請(qǐng)的Key

import相關(guān)類:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

import com.baidu.trace.Trace; 
import com.baidu.trace.LBSTraceClient; 
import com.baidu.trace.model.OnCustomAttributeListener;import com.baidu.trace.model.OnTraceListener;import com.baidu.trace.api.track.OnTrackListener; 
import com.baidu.trace.api.fence.OnFenceListener; 
import com.baidu.trace.api.entity.OnEntityListener;import com.baidu.trace.api.analysis.OnAnalysisListener;import com.baidu.trace.api.bos.OnBosListener;

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

以上就是官網(wǎng)上配置工程一節(jié)的介紹。

  結(jié)果,震驚的是,官方demo竟然調(diào)不起來,看Log

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

看了論壇的帖子,才意識(shí)到我上面獲取的是發(fā)布版本的SHA1,而調(diào)試的時(shí)候應(yīng)該用debug的SHA1,那我想的對(duì)不對(duì)試試就知道了

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

deblug的SHA1:B2:31:7E:C6:53:FE:4A:1B:E6:C8:B0:24:F5:0A:F5:E4:07:60:A6:BA

release的SHA1:02:D4:70:1E:FD:31:AA:C0:E9:8B:05:E7:DF:0C:DC:99:5D:84:4A:0A

那拿著這個(gè)字符串再去百度申請(qǐng)ak,結(jié)果,我沉默了,又走了彎路,還是沒調(diào)起來。

我真是醉了,我在命令行拿到的SHA1竟然和論壇下載的工具獲得的SHA1不一樣。日狗了。換了SHA1重新設(shè)置一下調(diào)起來了。接下來就是分析demo移植了。

   第二天咱們來分析demo中是如何獲得 手機(jī)位置信息并繪制軌跡曲線的。

在TrackApplication中的OnCreate(),

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 1  @Override 2     public void onCreate() { 3         super.onCreate(); 4         mContext = getApplicationContext(); 5         entityName = CommonUtil.getImei(this); 6         // 若為創(chuàng)建獨(dú)立進(jìn)程,則不初始化成員變量 7         if ("com.baidu.track:remote".equals(CommonUtil.getCurProcessName(mContext))) { 8             return; 9         }10         SDKInitializer.initialize(mContext);11         initView();12         initNotification();13         mClient = new LBSTraceClient(mContext);14         mTrace = new Trace(serviceId, entityName);15         mTrace.setNotification(notification);16         trackConf = getSharedPreferences("track_conf", MODE_PRIVATE);17         locRequest = new LocRequest(serviceId);18         mClient.setOnCustomAttributeListener(new OnCustomAttributeListener() {19             @Override20             public Map<String, String> onTrackAttributeCallback() {21                 Map<String, String> map = new HashMap<>();22                 map.put("key1", "value1");23                 map.put("key2", "value2");24                 return map;25             }26         });27         clearTraceStatus();28     }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

做了一部分初始化的工作:entityName是設(shè)備的IMEI號(hào),在通知欄添加了應(yīng)用通知Notification告知用戶服務(wù)正在運(yùn)行,實(shí)例化軌跡客戶端LBSTraceClient、軌跡服務(wù)Trace,Trace有多個(gè)構(gòu)造方法,并且給軌跡服務(wù)設(shè)置Notification。創(chuàng)建SharedPreference來存儲(chǔ)軌跡服務(wù)的配置信息。實(shí)例化定位請(qǐng)求LocRequest,mClient.setOnCustomAttributeListener()是為了自定義參數(shù),官方解釋是:

  為實(shí)現(xiàn)自定義屬性數(shù)據(jù)上傳,開發(fā)者須重寫OnCustomAttributeListener監(jiān)聽器中的onTrackAttributeCallback()接口,調(diào)用 LBSTraceClient.setOnCustomAttributeListener()方法設(shè)置自定義屬性監(jiān)聽器,并按照設(shè)置的定位周期更新onTrackAttributeCallback()的返回值。SDK每采集一次軌跡,便會(huì)自動(dòng)回調(diào)onTrackAttributeCallback()接口,獲取屬性值并寫入當(dāng)前軌跡點(diǎn)的屬性字段中。自定義屬性監(jiān)聽器需通過LBSTraceClient.setOnCustomAttributeListener()進(jìn)行設(shè)置,LBSTraceService只回調(diào)最新設(shè)置的自定義監(jiān)聽器。onTrackAttributeCallback()的返回值是Map<String, String>類型,每個(gè)對(duì)象都是一個(gè)<key,value>對(duì),其中key為entity的自定義字段名稱,value為值。

clearTraceStatus():

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

/**
     * 清除Trace狀態(tài):初始化app時(shí),判斷上次是正常停止服務(wù)還是強(qiáng)制殺死進(jìn)程,根據(jù)trackConf中是否有is_trace_started字段進(jìn)行判斷。
     * <p>
     * 停止服務(wù)成功后,會(huì)將該字段清除;若未清除,表明為非正常停止服務(wù)。     */
    private void clearTraceStatus() {        if (trackConf.contains("is_trace_started") || trackConf.contains("is_gather_started")) {
            SharedPreferences.Editor editor = trackConf.edit();
            editor.remove("is_trace_started");
            editor.remove("is_gather_started");
            editor.apply();
        }
    }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

在TracingActivity如圖,Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)這個(gè)布局就是com.baidu.mapapi.map.MapView和下方兩個(gè)按鈕。在OnCreate()的init()初始化三個(gè)監(jiān)聽器和地圖繪制的一些工具類,主要關(guān)注點(diǎn)擊兩個(gè)按鈕后事件的邏輯。

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 1 private void init() { 2         initListener(); 3         trackApp = (TrackApplication) getApplicationContext(); 4         viewUtil = new ViewUtil(); 5         mapUtil = MapUtil.getInstance(); 6         mapUtil.init((MapView) findViewById(R.id.tracing_mapView)); 7         mapUtil.setCenter(trackApp); 8         startRealTimeLoc(Constants.LOC_INTERVAL); 9         powerManager = (PowerManager) trackApp.getSystemService(Context.POWER_SERVICE);10 11         traceBtn = (Button) findViewById(R.id.btn_trace);12         gatherBtn = (Button) findViewById(R.id.btn_gather);13         traceBtn.setOnClickListener(this);14         gatherBtn.setOnClickListener(this);15         setTraceBtnStyle();16         setGatherBtnStyle();17         notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);18     }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

第8行startRealTimeLoc()看方法名開啟實(shí)時(shí)定位,傳入實(shí)時(shí)定位間隔單位是秒,方法實(shí)例化了一個(gè)內(nèi)部類runnable,并把這個(gè)runnable對(duì)象發(fā)送到handler處理。這個(gè)runnable的子線程調(diào)用了TrackApplication的getCurrentLocation()獲取當(dāng)前位置。

public void startRealTimeLoc(int interval) {
        realTimeLocRunnable = new RealTimeLocRunnable(interval);
        realTimeHandler.post(realTimeLocRunnable);
    }

getCurrentLocation(OnEntityListener entityListener, OnTrackListener trackListener)需要傳入兩個(gè)監(jiān)聽器,在這個(gè)方法中,

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 1  /** 2      * 獲取當(dāng)前位置 3      */ 4     public void getCurrentLocation(OnEntityListener entityListener, OnTrackListener trackListener) { 5         // 網(wǎng)絡(luò)連接正常,開啟服務(wù)及采集,則查詢糾偏后實(shí)時(shí)位置;否則進(jìn)行實(shí)時(shí)定位 6         if (NetUtil.isNetworkAvailable(mContext) 7                 && trackConf.contains("is_trace_started") 8                 && trackConf.contains("is_gather_started") 9                 && trackConf.getBoolean("is_trace_started", false)10                 && trackConf.getBoolean("is_gather_started", false)) {11             LatestPointRequest request = new LatestPointRequest(getTag(), serviceId, entityName);12             ProcessOption processOption = new ProcessOption();13             processOption.setNeedDenoise(true);14             processOption.setRadiusThreshold(100);15             request.setProcessOption(processOption);16             mClient.queryLatestPoint(request, trackListener);17         } else {18             mClient.queryRealTimeLoc(locRequest, entityListener);19         }20     }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

判斷是否開啟了軌跡服務(wù)和軌跡采集和網(wǎng)絡(luò)連接確定查詢糾偏后實(shí)時(shí)位置或者進(jìn)行實(shí)時(shí)定位。構(gòu)造請(qǐng)求參數(shù)和選項(xiàng)請(qǐng)求位置。

  回到剛才的startRealTimeLoc(int interval),傳入的interval間隔也是handler發(fā)送消息的間隔。而這個(gè)handler在demo中只是簡(jiǎn)單的繼承Handler并沒有自定義handlerMessage()的邏輯。這就是個(gè)循環(huán)。輪詢?cè)O(shè)備的位置。

在初始化監(jiān)聽時(shí),OnTrackListener()重寫了onLatestPointCallback(LatestPointResponse response)方法,其中判斷response的返回碼以及返回的點(diǎn)不是原點(diǎn)后將點(diǎn)轉(zhuǎn)化為地圖上的點(diǎn)并調(diào)用mapUtil.updateStatus(currentLatLng,true)繪制點(diǎn)。OnEntityListener()重寫了onReceiveLocation(TraceLocation location),與上面類似。OnTraceListener()中重寫了開啟軌跡服務(wù)和采集服務(wù)成功失敗的回調(diào),

其中上圖的開啟采集是建立在開啟服務(wù)的基礎(chǔ)之上的。例如在開啟服務(wù)的回調(diào)中,成功的話將TrackApplication中的服務(wù)開啟標(biāo)志位置為true,并在SharedPreference中持久化,注冊(cè)廣播。停止服務(wù)的回調(diào)中,成功停掉的話把TrackApplication的兩個(gè)標(biāo)記位都置為false,并且移除SP的兩個(gè)key,解除廣播。

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 public void onStartTraceCallback(int errorNo, String message) {                if (StatusCodes.SUCCESS == errorNo || StatusCodes.START_TRACE_NETWORK_CONNECT_FAILED <= errorNo) {
                    trackApp.isTraceStarted = true;
                    SharedPreferences.Editor editor = trackApp.trackConf.edit();
                    editor.putBoolean("is_trace_started", true);
                    editor.apply();
                    setTraceBtnStyle();
                    registerReceiver();
                }
                viewUtil.showToast(TracingActivity.this,
                        String.format("onStartTraceCallback, errorNo:%d, message:%s ", errorNo, message));
            }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

if (StatusCodes.SUCCESS == errorNo || StatusCodes.CACHE_TRACK_NOT_UPLOAD == errorNo) {
                    trackApp.isTraceStarted = false;
                    http://www.cnblogs.com/henu529/p/7127774.html