先看下實現(xiàn)效果:



鷹眼是一套軌跡管理服務(wù),接入該服務(wù)后,可追蹤車輛/人員等運動物體,實現(xiàn)實時定位、軌跡追蹤和軌跡存儲查詢等功能?;邡椦厶峁┑慕涌诤驮贫朔?wù),可以迅速構(gòu)建一套完全屬于您自己的完整、精準(zhǔn)且高性能的軌跡管理系統(tǒng),可應(yīng)用于車隊管理、人員管理等領(lǐng)域。具體請查看官網(wǎng)介紹。

這篇文章就講一下如何在Android App中實現(xiàn)軌跡追蹤,既然要追蹤軌跡,肯定得先獲取這個設(shè)備的一系列軌跡點,這就需要我們在終端集成鷹眼服務(wù)。我們以Android手機(jī)為例,集成鷹眼軌跡SDK后,App將會按照我們設(shè)定的頻率主動采集實時軌跡。
什么是Android鷹眼軌跡SDK?
鷹眼軌跡是一套基于Android 2.1及以上版本設(shè)備的應(yīng)用程序接口, 可以通過該接口實現(xiàn)軌跡追蹤功能:
- 軌跡追蹤:按照設(shè)定的頻率主動采集實時軌跡
- 軌跡存儲:云端實現(xiàn)海量軌跡數(shù)據(jù)存儲
- 軌跡查詢:查詢被追蹤者實時位置、歷史軌跡和里程
- 軌跡糾偏:云端對軌跡進(jìn)行實時去噪、綁路、抽稀處理,解決軌跡偏移問題
- 地理圍欄:當(dāng)被追蹤者進(jìn)出一定范圍(圓形、多邊形、線型、行政區(qū))的虛擬地理區(qū)域時,監(jiān)控者可以接收到自動報警通知
- 圖像存儲:支持隨軌跡上傳、存儲和查詢圖像文件
接入鷹眼服務(wù)
開發(fā)工具:Android Studio
一. 獲取AK
使用百度鷹眼Android SDK,需要先獲取服務(wù)密鑰(AK),申請地址:http://lbsyun.baidu.com/apiconsole/key,申請時需要用到開發(fā)版SHA1值和發(fā)布版SHA1值,詳細(xì)教程可查看:Android獲取SHA1(開發(fā)版和發(fā)布版)
二. 創(chuàng)建鷹眼服務(wù)
1. 創(chuàng)建服務(wù)
進(jìn)入鷹眼軌跡管理平臺,點擊"創(chuàng)建服務(wù)"按鈕,在彈窗中填寫信息后完成服務(wù)創(chuàng)建。

2. 獲取 service_id
創(chuàng)建服務(wù)成功后即可列表左側(cè)的"系統(tǒng) ID(service_id)",如:217548,即為訪問該service的唯一標(biāo)識,在后續(xù)的接口調(diào)用中均要使用。

三. 接入鷹眼服務(wù)
1. 配置庫文件
SDK下載地址:http://lbsyun.baidu.com/index.php?title=android-yingyan/sdkandev-download
下載的壓縮包解壓后將jar包和so文件復(fù)制到項目lib目錄下,并在app build.gradle的android標(biāo)簽中加入如下代碼并Sync Now。
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
2. 設(shè)置AndroidManifest.xml
<service
android:name="com.baidu.trace.LBSTraceService"
android:enabled="true"
android:process=":remote"/>
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="上面申請的ak值" />
3. 加入相關(guān)權(quán)限
<!-- 這個權(quán)限用于進(jìn)行網(wǎng)絡(luò)定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 這個權(quán)限用于訪問GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 用于訪問wifi網(wǎng)絡(luò)信息,wifi信息會用于進(jìn)行網(wǎng)絡(luò)定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- 獲取運營商信息,用于支持提供運營商信息相關(guān)的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 這個權(quán)限用于獲取wifi的獲取權(quán)限,wifi信息會用來進(jìn)行網(wǎng)絡(luò)定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- 寫入擴(kuò)展存儲,向擴(kuò)展卡寫入數(shù)據(jù),用于寫入對象存儲BOS數(shù)據(jù)-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 訪問網(wǎng)絡(luò),網(wǎng)絡(luò)定位需要上網(wǎng)-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android O之后開啟前臺服務(wù)需要申請該權(quán)限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android Q之后,后臺定位需要申請該權(quán)限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- 以下不是鷹眼SDK需要的基礎(chǔ)權(quán)限,可選 -->
<!-- 用于加快GPS首次定位,可選權(quán)限,非必須-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<!-- 用于Android M及以上系統(tǒng),申請加入忽略電池優(yōu)化白名單,可選權(quán)限,非必須-->
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
4. 初始化軌跡服務(wù)
// 軌跡服務(wù)ID
long serviceId = 0;
// 設(shè)備標(biāo)識
String entityName = "myTrace";
// 是否需要對象存儲服務(wù),默認(rèn)為:false,關(guān)閉對象存儲服務(wù)。注:鷹眼 Android SDK v3.0以上版本支持隨軌跡上傳圖像等對象數(shù)據(jù),若需使用此功能,該參數(shù)需設(shè)為 true,且需導(dǎo)入bos-android-sdk-1.0.2.jar。
boolean isNeedObjectStorage = false;
// 初始化軌跡服務(wù)
Trace mTrace = new Trace(serviceId, entityName, isNeedObjectStorage);
// 初始化軌跡服務(wù)客戶端
LBSTraceClient mTraceClient = new LBSTraceClient(getApplicationContext());
5. 設(shè)置定位和回傳周期
鷹眼軌跡數(shù)據(jù)傳輸采取定期打包回傳的方式,以節(jié)省流量。開發(fā)者可以自定義定位頻率和打包回傳頻率,頻率可設(shè)置范圍為:2~300秒。例如:定位頻率為5s,打包回傳頻率為10s,則2次定位后打包回傳一次。
// 定位周期(單位:秒)
int gatherInterval = 5;
// 打包回傳周期(單位:秒)
int packInterval = 10;
// 設(shè)置定位和打包周期
mTraceClient.setInterval(gatherInterval, packInterval);
6. 初始化監(jiān)聽器
// 初始化軌跡服務(wù)監(jiān)聽器
OnTraceListener mTraceListener = new OnTraceListener() {
/**
* 綁定服務(wù)回調(diào)接口
* @param i 狀態(tài)碼
* @param s 消息 0:成功 1:失敗
*/
@Override
public void onBindServiceCallback(int i, String s) {
Log.e(TAG,"綁定服務(wù)回調(diào)");
Log.e(TAG,i+"");
Log.e(TAG,s+"");
}
/**
* 開啟服務(wù)回調(diào)接口
* @param status 狀態(tài)碼
* @param message 消息
* <pre>0:成功 </pre>
* <pre>10000:請求發(fā)送失敗</pre>
* <pre>10001:服務(wù)開啟失敗</pre>
* <pre>10002:參數(shù)錯誤</pre>
* <pre>10003:網(wǎng)絡(luò)連接失敗</pre>
* <pre>10004:網(wǎng)絡(luò)未開啟</pre>
* <pre>10005:服務(wù)正在開啟</pre>
* <pre>10006:服務(wù)已開啟</pre>
*/
@Override
public void onStartTraceCallback(int status, String message) {
Log.e(TAG,"開啟服務(wù)回調(diào)");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 停止服務(wù)回調(diào)接口
* @param status 狀態(tài)碼
* @param message 消息
* <pre>0:成功</pre>
* <pre>11000:請求發(fā)送失敗</pre>
* <pre>11001:服務(wù)停止失敗</pre>
* <pre>11002:服務(wù)未開啟</pre>
* <pre>11003:服務(wù)正在停止</pre>
*/
@Override
public void onStopTraceCallback(int status, String message) {
Log.e(TAG,"停止服務(wù)回調(diào)");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 開啟采集回調(diào)接口
* @param status 狀態(tài)碼
* @param message 消息
* <pre>0:成功</pre>
* <pre>12000:請求發(fā)送失敗</pre>
* <pre>12001:采集開啟失敗</pre>
* <pre>12002:服務(wù)未開啟</pre>
*/
@Override
public void onStartGatherCallback(int status, String message) {
Log.e(TAG,"開啟采集回調(diào)");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 停止采集回調(diào)接口
* @param status 狀態(tài)碼
* @param message 消息
* <pre>0:成功</pre>
* <pre>13000:請求發(fā)送失敗</pre>
* <pre>13001:采集停止失敗</pre>
* <pre>13002:服務(wù)未開啟</pre>
*/
@Override
public void onStopGatherCallback(int status, String message) {
Log.e(TAG,"停止采集回調(diào)");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 推送消息回調(diào)接口
*
* @param messageNo 狀態(tài)碼
* @param message 消息
* <pre>0x01:配置下發(fā)</pre>
* <pre>0x02:語音消息</pre>
* <pre>0x03:服務(wù)端圍欄報警消息</pre>
* <pre>0x04:本地圍欄報警消息</pre>
* <pre>0x05~0x40:系統(tǒng)預(yù)留</pre>
* <pre>0x41~0xFF:開發(fā)者自定義</pre>
*/
@Override
public void onPushCallback(byte messageNo, PushMessage message) {
Log.e(TAG,"推送消息回調(diào)");
Log.e(TAG,messageNo+"");
Log.e(TAG,message+"");
}
@Override
public void onInitBOSCallback(int i, String s) {
}
};
7. 開啟軌跡追蹤
開啟軌跡追蹤需要進(jìn)行以下兩步操作:
(1)開啟鷹眼服務(wù),啟動鷹眼 service
// 開啟服務(wù)
mTraceClient.startTrace(mTrace, mTraceListener);
(2)開啟軌跡采集,啟動軌跡追蹤。
// 開啟采集
mTraceClient.startGather(mTraceListener);
至此,正式開啟軌跡追蹤。
8. 結(jié)束軌跡追蹤
結(jié)束軌跡追蹤時,可以有兩種選擇:
(1)停止軌跡服務(wù):此方法將同時停止軌跡服務(wù)和軌跡采集,完全結(jié)束鷹眼軌跡服務(wù)。若需再次啟動軌跡追蹤,需重新啟動服務(wù)和軌跡采集,示例代碼如下:
// 停止服務(wù)
mTraceClient.stopTrace(mTrace, mTraceListener);
(2)停止軌跡采集:此方法將停止軌跡采集,但不停止軌跡服務(wù)(即,不再采集軌跡點了,但鷹眼 service 還存活)。
// 停止采集
mTraceClient.stopGather(mTraceListener);
接入鷹眼服務(wù)按照官方文檔很容易實現(xiàn),在實際項目中其實經(jīng)常需要后臺運行,所以可以將這些邏輯放到 service 中來實現(xiàn),然后做相應(yīng)的服務(wù)?;?,讓其在后臺進(jìn)行軌跡采集。而像軌跡服務(wù)、軌跡服務(wù)客戶端這些對象或變量可以放到 application 中,以方便在整個應(yīng)用中使用。
四、自定義屬性上傳
1. 軌跡點自定義屬性數(shù)據(jù)上傳
顧名思義,軌跡點自定義屬性數(shù)據(jù)上傳就是針對每一個軌跡點增加上傳的自定義屬性字段,軌跡中的每個位置點可擁有一系列開發(fā)者自定義的描述字段,如汽車的電量、發(fā)動機(jī)轉(zhuǎn)速等,用以記錄行程中的實時狀態(tài)信息。
為實現(xiàn)自定義屬性數(shù)據(jù)上傳,開發(fā)者須重寫OnCustomAttributeListener監(jiān)聽器中的onTrackAttributeCallback()接口,調(diào)用 LBSTraceClient.setOnCustomAttributeListener()方法設(shè)置自定義屬性監(jiān)聽器,并按照設(shè)置的定位周期更新onTrackAttributeCallback()的返回值,示例如下:
// 為實現(xiàn)自定義屬性數(shù)據(jù)上傳,須重寫OnCustomAttributeListener監(jiān)聽器中的onTrackAttributeCallback()接口
mTraceClient.setOnCustomAttributeListener(new OnCustomAttributeListener() {
@Override
public Map<String, String> onTrackAttributeCallback() {
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
return map;
}
//l - 回調(diào)時定位點的時間戳(毫秒)
@Override
public Map<String, String> onTrackAttributeCallback(long l) {
return null;
}
});
SDK每采集一次軌跡,便會自動回調(diào)onTrackAttributeCallback()接口,獲取屬性值并寫入當(dāng)前軌跡點的屬性字段中。onTrackAttributeCallback()的返回值是Map<String, String>類型,每個對象都是一個<key,value>對,其中key為自定義字段名稱,value為值。
2. 自定義entity屬性上傳
這里先說明一下,上面的軌跡點自定義屬性上傳指的是每一個軌跡點增加上傳的自定義屬性字段。我們目前每一個設(shè)備有一個設(shè)備標(biāo)識,也就是在初始化軌跡服務(wù)傳入的 entityName ,那如果我們還需要上傳當(dāng)前這個entity的其他屬性,比如用戶姓名、年齡或性別等該如何做呢?
方式一:通過調(diào)用 addEntity() 方法主動添加
這種方式等于我們主動添加一個entity,也就不需要我們在初始化軌跡服務(wù)傳入 entityName ,addEntity()方法需要傳入兩個參數(shù),具體使用方式可以看鷹眼SDK的API文檔,示例如下:
AddEntityRequest request = new AddEntityRequest();
request.setServiceId(serviceId);
request.setEntityName(entityName);
Map<String, String> columns = new HashMap<String, String>();
columns.put("USER_ID", "1001");
columns.put("USER_SEX", "男");
columns.put("ACC_NBR", "1234567890");
request.setColumns(columns);
mTraceClient.addEntity(request, new OnEntityListener() {
@Override
public void onAddEntityCallback(AddEntityResponse addEntityResponse) {
super.onAddEntityCallback(addEntityResponse);
}
});
方式二:通過調(diào)用 updateEntity() 方法指定自定義屬性
如果我們在初始化軌跡服務(wù)傳入了entityName ,服務(wù)端將會自動創(chuàng)建以entityName命名的entity。由于服務(wù)端自動創(chuàng)建的entity不包含自定義屬性的值,若需要指定entity自定義屬性,需要再調(diào)用updateEntity()方法,通過columnKey字段指定自定義屬性的值。
示例如下:
//自定義entity屬性上傳
UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest();
updateEntityRequest.setServiceId(serviceId);
updateEntityRequest.setEntityName(entityName);
Map<String, String> columns = new HashMap<String, String>();
columns.put("USER_ID", "1001");
columns.put("USER_SEX", "男");
columns.put("ACC_NBR", "1234567890");
updateEntityRequest.setColumns(columns);
mTraceClient.updateEntity(updateEntityRequest, new OnEntityListener() {
@Override
public void onAddEntityCallback(AddEntityResponse addEntityResponse) {
super.onAddEntityCallback(addEntityResponse);
}
});
最后附上源碼地址:https://download.csdn.net/download/xch_yang/85595480
原創(chuàng)不易,轉(zhuǎn)載請注明出處。