百度地圖之百度鷹眼軌跡使用
拿外賣配送爲例,配送員從接單開始上傳行駛軌跡,用戶端可以實時查看配送員的行駛軌跡,對於點外賣的用戶來說可以更直接地觀察到自己的訂單是否在配送過程中,不再需要一遍一遍地撥打商戶電話催促。
在思考相關解決方案的時候第一個想到的是在後臺不斷地獲取配送員的經緯度,上傳到服務器,然後在用戶端實時地刷新這些經緯度數據顯示到地圖上。這種方法雖說思路很簡單,只是數據的上傳與刷新,但是軌跡的準確度與定位的精準度有很大關係,如果遇到網絡環境較弱等的情況,定位經緯度數據一定是東歪西扭的,顯示在地圖上的軌跡信息也是橫七豎八的。
後臺發現百度地圖上線了鷹眼軌跡服務的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
使用過百度定位功能的同學就知道使用方法了
接下來到http://lbsyun.baidu.com/index.php?title=yingyan/manage
創建鷹眼服務,得到一個服務ID,用於在代碼中初始化鷹眼服務
將開發包導入項目中
若使用了百度地圖其他的SDK,請到http://lbsyun.baidu.com/index.php?title=androidsdk/sdkandev-download
選擇下載在項目中有用到的功能,切記不要單獨下載每一個SDK,否則會引起包之間的衝突,這一點被百度坑的心累。
選擇下載完統一的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上查詢配送員的軌跡將陸續在後面的文章提到。