Android百度鷹眼軌跡
作者:短工邦技術部 - 陳文超
百度地圖之百度鷹眼軌跡使用
拿外賣配送為例,配送員從接單開始上傳行駛軌跡,使用者端可以實時檢視配送員的行駛軌跡,對於點外賣的使用者來說可以更直接地觀察到自己的訂單是否在配送過程中,不再需要一遍一遍地撥打商戶電話催促。
在思考相關解決方案的時候第一個想到的是在後臺不斷地獲取配送員的經緯度,上傳到伺服器,然後在使用者端實時地重新整理這些經緯度資料顯示到地圖上。這種方法雖說思路很簡單,只是資料的上傳與重新整理,但是軌跡的準確度與定位的精準度有很大關係,如果遇到網路環境較弱等的情況,定位經緯度資料一定是東歪西扭的,顯示在地圖上的軌跡資訊也是橫七豎八的。
後臺發現百度地圖上線了鷹眼軌跡服務的SDK,可以實現對某個物件的軌跡追蹤,並顯示在百度地圖上,看起來就是我們想要的功能,那我們就先來實現這個SDK的功能。
首先得在API控制檯建立新的應用,應用型別為Android應用,把全部API都勾上,最近建立新的應用增加了“釋出版SHA1”、“開發板SHA1”,大大方便了對於除錯狀態下的功能開發,以及簽名上線後由於簽名SHA1的改變而導致無法初始化SDK的問題。
開發版SHA1的獲取:
可以在eclipse中直接檢視:windows -> preferance -> android -> build
釋出版SHA1的獲取:
使用keytool
第1步:執行進入控制檯
第2步:定位到.android資料夾下,輸入cd .android
第3步:輸入keytool -list -v -keystore debug.keystore,會得到三種指紋證書,選取SHA1型別的證書(金鑰口令是android),例如:
其中keytool為jdk自帶工具;debug.keystore為Android 簽名證書檔案的完整路徑
建立成功後可以在控制檯得到相應的AK,在工程AndroidManifest.xml需要配置該AK
使用過百度定位功能的同學就知道使用方法了
將開發包匯入專案中
選擇下載完統一的SDK後匯入相關so檔案和jar,鷹眼的SDK只需要匯入jar包和armeabi就可以了,x86、x86_64不需要匯入,否則百度又會出現初始化失敗的問題。若有使用到JPush極光推送的SDK,也只需要匯入jar包和armeabi就可以了,否則也會衝突。(真感覺百度的SDK的相容性真是讓人捉急,很容易出現庫與庫之間的衝突(/”≡ _ ≡)/~┴┴)
接下來可以開始工程的配置了,
首頁將第一步建立應用獲得的AK配置到AndroidManifest.xml
<application>
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="AK key" />
<service
android:name="com.baidu.trace.LBSTraceService"
android:enabled="true"
android:exported="true" >
</service>
<service
<!-- 我們自己的軌跡服務 -->
android:name="com.mcandmc.xxxxxxx.service.MyService"
android:enabled="true"
android:exported="false"
android:process=":track" >
</service>
</application>
新增各種許可權
<!-- 這個許可權用於進行網路定位-->
<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.BLUETOOTH"/>
<!--允許程式發現和配對藍芽裝置-->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- 用於讀取手機當前的狀態-->
<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" />
<!--允許應用讀取低級別的系統日誌檔案 -->
<uses-permission android:name="android.permission.READ_LOGS" />
<!--允許訪問振動裝置-->
<uses-permission android:name="android.permission.VIBRATE" />
<!--螢幕保持喚醒 不鎖屏-->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--允許應用程式更改主螢幕中的設定和快捷方式-->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
核心程式碼
public class MyService extends Service{
private static final String TAG = "MyService";
// 軌跡服務
protected static Trace trace = null;
// 鷹眼服務ID,開發者建立的鷹眼服務對應的服務ID
public static final long serviceId = xxxxxxxx;
// 軌跡服務型別
//0 : 不建立socket長連線,
//1 : 建立socket長連線但不上傳位置資料,
//2 : 建立socket長連線並上傳位置資料)
private int traceType = 2;
// 軌跡服務客戶端
public static LBSTraceClient client = null;
// Entity監聽器
public static OnEntityListener entityListener = null;
// 開啟軌跡服務監聽器
protected OnStartTraceListener startTraceListener = null;
// 停止軌跡服務監聽器
protected static OnStopTraceListener stopTraceListener = null;
// 採集週期(單位 : 秒)
private int gatherInterval = 10;
// 設定打包週期(單位 : 秒)
private int packInterval = 20;
protected static boolean isTraceStart = false;
// 手機IMEI號設定為唯一軌跡標記號,只要該值唯一,就可以作為軌跡的標識號,使用相同的標識將導致軌跡混亂
private String imei;
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null && intent.getExtras() != null){
imei= intent.getStringExtra("imei");
}
init();
return super.onStartCommand(intent, START_STICKY, startId);
}
//被銷燬時反註冊廣播接收器
public void onDestroy() {
super.onDestroy();
stopTrace();
}
/**
* 初始化
*/
private void init() {
// 初始化軌跡服務客戶端
client = new LBSTraceClient(this);
// 設定定位模式
client.setLocationMode(LocationMode.High_Accuracy);
// 初始化軌跡服務
trace = new Trace(this, serviceId, imei, traceType);
// 採集週期,上傳週期
client.setInterval(gatherInterval, packInterval);
// 設定http請求協議型別0:http,1:https
client.setProtocolType(0);
// 初始化監聽器
initListener();
// 啟動軌跡上傳
startTrace();
}
// 開啟軌跡服務
private void startTrace() {
// 通過軌跡服務客戶端client開啟軌跡服務
client.startTrace(trace, startTraceListener);
}
// 停止軌跡服務
public static void stopTrace() {
// 通過軌跡服務客戶端client停止軌跡服務
LogUtil.i(TAG, "stopTrace(), isTraceStart : " + isTraceStart);
if(isTraceStart){
client.stopTrace(trace, stopTraceListener);
}
}
// 初始化監聽器
private void initListener() {
initOnEntityListener();
// 初始化開啟軌跡服務監聽器
initOnStartTraceListener();
// 初始化停止軌跡服務監聽器
initOnStopTraceListener();
}
/**
* 初始化OnStartTraceListener
*/
private void initOnStartTraceListener() {
// 初始化startTraceListener
startTraceListener = new OnStartTraceListener() {
// 開啟軌跡服務回撥介面(arg0 : 訊息編碼,arg1 : 訊息內容,詳情檢視類參考)
public void onTraceCallback(int arg0, String arg1) {
LogUtil.i(TAG, "開啟軌跡回撥介面 [訊息編碼 : " + arg0 + ",訊息內容 : " + arg1 + "]");
if (0 == arg0 || 10006 == arg0) {
isTraceStart = true;
}
}
// 軌跡服務推送介面(用於接收服務端推送訊息,arg0 : 訊息型別,arg1 : 訊息內容,詳情檢視類參考)
public void onTracePushCallback(byte arg0, String arg1) {
LogUtil.i(TAG, "軌跡服務推送介面訊息 [訊息型別 : " + arg0 + ",訊息內容 : " + arg1 + "]");
}
};
}
// 初始化OnStopTraceListener
private void initOnStopTraceListener() {
stopTraceListener = new OnStopTraceListener() {
// 軌跡服務停止成功
public void onStopTraceSuccess() {
LogUtil.i(TAG, "停止軌跡服務成功");
isTraceStart = false;
stopSelf();
}
// 軌跡服務停止失敗(arg0 : 錯誤編碼,arg1 : 訊息內容,詳情檢視類參考)
public void onStopTraceFailed(int arg0, String arg1) {
LogUtil.i(TAG, "停止軌跡服務介面訊息 [錯誤編碼 : " + arg0 + ",訊息內容 : " + arg1 + "]");
}
};
}
// 初始化OnEntityListener
private void initOnEntityListener() {
entityListener = new OnEntityListener() {
// 請求失敗回撥介面
@Override
public void onRequestFailedCallback(String arg0) {method stub
Looper.prepare();
LogUtil.i(TAG, "entity請求失敗回撥介面訊息 : " + arg0);
Toast.makeText(getApplicationContext(), "entity請求失敗回撥介面訊息 : " + arg0, Toast.LENGTH_SHORT).show();
Looper.loop();
}
// 新增entity回撥介面
@Override
public void onAddEntityCallback(String arg0) {
Looper.prepare();
LogUtil.i(TAG, "新增entity回撥介面訊息 : " + arg0);
Toast.makeText(getApplicationContext(), "新增entity回撥介面訊息 : " + arg0, Toast.LENGTH_SHORT).show();
Looper.loop();
}
// 查詢entity列表回撥介面
@Override
public void onQueryEntityListCallback(String message) {
LogUtil.i(TAG, "onQueryEntityListCallback : " + message);
}
@Override
public void onReceiveLocation(TraceLocation location) {
}
};
}
}
在Activity中啟動Servise
Intent intent = new Intent();
intent.putExtra("imei", "xxxxxx");
intent.setClass(this, MyService.class);
startService(intent);
這樣APP就會在後臺默默地上傳軌跡啦
如果要檢視軌跡是否上傳成功,可以在軌跡管理臺檢視,至於如何實現在APP上查詢配送員的軌跡將陸續在後面的文章提到。