1. 程式人生 > >呼叫百度鷹眼api實現實時軌跡繪製

呼叫百度鷹眼api實現實時軌跡繪製

自己想做一個跑步路徑軌跡記錄的app,剛好百度地圖有鷹眼api,就拿過來呼叫了,這裡給出鷹眼api呼叫的一個完整實現的例子HelloTrace,放在了完整包的下載連結為:http://download.csdn.net/detail/sinat_22013331/9323045

最近缺下載積分,所以需要一個下載幣。。只要一個。。

百度鷹眼api介面的實現,在實現之前要進行工程配置,這是第一步,在AndroidManifest.xml檔案中配置的資訊是

        <meta-data
        	android:name="com.baidu.lbsapi.API_KEY"
        	android:value="百度接入AK" />

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

這個配置資訊要放在<application>的子項裡。其中的AK值是需要在百度開發者中心自己做申請的。ak的申請地址是:點選開啟連結

在這個申請的時候需要注意,ak申請的設定裡面,安全碼的實現是用SHA1和應用的包名組合在一起的,這裡要注意packet的名稱,一個包名只能對應一個ak值,如果對應的包名不對,就會出現errcode為230的情況,scode有誤。

配置過後要把相關的JAR包導進工程裡。

第二步:要申請一個鷹眼服務帳號,獲得service_id,在主執行緒中定義這個service_id。

第三步:設定輸出介面,在輸出介面中包含一個MapView,用來展示實時的trace資訊

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.blyang.MainActivity" >

    <com.baidu.mapapi.map.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        />

</LinearLayout>


第四步:定義初始的變數

    	int gatherInterval = 3;  //位置採集週期 (s)
    	int packInterval = 10;  //打包週期 (s)
    	String entityName = null;  // entity標識
    	long serviceId = 你的service_id;// 鷹眼服務ID
   	int traceType = 2;  //軌跡服務型別
    	private static OnStartTraceListener startTraceListener = null;  //開啟軌跡服務監聽器
    
	private static MapView mapView = null;
	private static BaiduMap baiduMap = null;
	private static OnEntityListener entityListener = null;
	private RefreshThread refreshThread = null;  //重新整理地圖執行緒以獲取實時點
	private static MapStatusUpdate msUpdate = null;
	private static BitmapDescriptor realtimeBitmap;  //圖示
	private static OverlayOptions overlay;  //覆蓋物
	private static List<LatLng> pointList = new ArrayList<LatLng>();  //定位點的集合
	private static PolylineOptions polyline = null;  //路線覆蓋物
	
	
    	private Trace trace;  // 例項化軌跡服務
    	private LBSTraceClient client;  // 例項化軌跡服務客戶端


第五步:onCreate方法的實現

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		SDKInitializer.initialize(getApplicationContext());
		
		setContentView(R.layout.activity_main);  //設定主介面
		
		init();  //相關變數初始化
		
		initOnEntityListener();  //初始化實體監聽器
		
		initOnStartTraceListener();  //初始化軌跡追蹤監聽器
		
		client.startTrace(trace, startTraceListener);  // 開啟軌跡服務
	}

其中init()方法為相關變數的初始化,這個方法體如下:
	/**
	 * 初始化各個引數
	 */
	 private void init() {
		 
		 mapView = (MapView) findViewById(R.id.mapView);
		 baiduMap = mapView.getMap();
		 mapView.showZoomControls(false);
		 
		 entityName = getImei(getApplicationContext());  //手機Imei值的獲取,用來充當實體名
		 
         client = new LBSTraceClient(getApplicationContext());  //例項化軌跡服務客戶端
         
         trace = new Trace(getApplicationContext(), serviceId, entityName, traceType);  //例項化軌跡服務
         
         client.setInterval(gatherInterval, packInterval);  //設定位置採集和打包週期
	 }

實體監聽器的初始化方法為initOnEntityListener()方法,在這個方法中定義實體的相關操作,方法體如下:
	 /**
	  * 初始化設定實體狀態監聽器
	  */
	 private void initOnEntityListener(){
		 
		 //實體狀態監聽器
		 entityListener = new OnEntityListener(){

			@Override
			public void onRequestFailedCallback(String arg0) {
				Looper.prepare();
				Toast.makeText(
						getApplicationContext(), 
						"entity請求失敗的回撥介面資訊:"+arg0, 
						Toast.LENGTH_SHORT)
						.show();
				Looper.loop();
			}
			
			@Override
			public void onQueryEntityListCallback(String arg0) {
				/**
				 * 查詢實體集合回撥函式,此時呼叫實時軌跡方法
				 */
				showRealtimeTrack(arg0);  
			}
			
		 };
	 }
	 
在其中的查詢實體集合的回撥方法中,要呼叫showRealtimeTrack方法,用來展示實時的路徑資訊,這個方法在下面會詳細講到。

接著,要初始化啟動軌跡監聽器initOnStartTraceListener,開啟運動實體的軌跡追蹤。這個監聽器的內部方法體如下:

	/**
	 *  追蹤開始 
	 */
	private void initOnStartTraceListener() {
		
		// 例項化開啟軌跡服務回撥介面
		startTraceListener = new OnStartTraceListener() {
			// 開啟軌跡服務回撥介面(arg0 : 訊息編碼,arg1 : 訊息內容,詳情檢視類參考)
			@Override
			public void onTraceCallback(int arg0, String arg1) {
				Log.i("TAG", "onTraceCallback=" + arg1);
				if(arg0 == 0 || arg0 == 10006){
					startRefreshThread(true);
				}
			}

			// 軌跡服務推送介面(用於接收服務端推送訊息,arg0 : 訊息型別,arg1 : 訊息內容,詳情檢視類參考)
			@Override
			public void onTracePushCallback(byte arg0, String arg1) {
				Log.i("TAG", "onTracePushCallback=" + arg1);
			}
		};
		
	}
在這個監聽器的軌跡回撥方法中,要呼叫重新整理執行緒,實現不斷的採集使用者的位置點。

重新整理執行緒的實現如下:

	/**
	 * 啟動重新整理執行緒
	 * @param isStart
	 */
	private void startRefreshThread(boolean isStart){
		
		if(refreshThread == null){
			refreshThread = new RefreshThread();
		}
		
		refreshThread.refresh = isStart;
		
		if(isStart){
			if(!refreshThread.isAlive()){
				refreshThread.start();
			}
		}
		else{
			refreshThread = null;
		}
		
	}
重新整理執行緒的run方法如下:
	/**
	 * 軌跡重新整理執行緒
	 * @author BLYang
	 */
	private class RefreshThread extends Thread{
		 
		protected boolean refresh = true;  
		
		public void run(){
			
			while(refresh){
				queryRealtimeTrack();
				try{
					Thread.sleep(packInterval * 1000);
				}catch(InterruptedException e){
					System.out.println("執行緒休眠失敗");
				}
			}
			
		}
	}
	 
	/**
	 * 查詢實時線路
	 */
	private void queryRealtimeTrack(){
		
		String entityName = this.entityName;
		String columnKey = "";
		int returnType = 0;
		int activeTime = 0;
		int pageSize = 10;
		int pageIndex = 1;
		
		this.client.queryEntityList(
				serviceId, 
				entityName, 
				columnKey, 
				returnType,
				activeTime, 
				pageSize, 
				pageIndex, 
				entityListener
				);
		
	}
	
在run方法中要呼叫查詢實時線路的方法,不斷的查詢使用者的當前位置點

在onCreate()方法的最後,啟動軌跡追蹤。

client.startTrace(trace, startTraceListener);  // 開啟軌跡服務
在這個方法中呼叫startTraceListener,開啟追蹤服務。

這樣就實現的軌跡追蹤,但是隻有這些方法並不能實時的顯示追蹤資訊。

現在,再回去initOnEntityListener方法,在這個方法中要實現showRealtimeTrack()方法,這個方法就是用來實時展示的方法

	/**
	 * 展示實時線路圖
	 * @param realtimeTrack
	 */
	protected void showRealtimeTrack(String realtimeTrack){
		
		if(refreshThread == null || !refreshThread.refresh){
			return;
		}
		
		//資料以JSON形式存取
		RealtimeTrackData realtimeTrackData = GsonService.parseJson(realtimeTrack, RealtimeTrackData.class);
		
		if(realtimeTrackData != null && realtimeTrackData.getStatus() ==0){
			
			LatLng latLng = realtimeTrackData.getRealtimePoint();
			
			if(latLng != null){
				pointList.add(latLng);
				drawRealtimePoint(latLng);
			}
			else{
				Toast.makeText(getApplicationContext(), "當前無軌跡點", Toast.LENGTH_LONG).show();
			}
			
		}
		
	}
	
	/**
	 * 畫出實時線路點
	 * @param point
	 */
	private void drawRealtimePoint(LatLng point){
		
		baiduMap.clear();
		MapStatus mapStatus = new MapStatus.Builder().target(point).zoom(18).build();
		msUpdate = MapStatusUpdateFactory.newMapStatus(mapStatus);
		realtimeBitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_gcoding);
		overlay = new MarkerOptions().position(point)
				.icon(realtimeBitmap).zIndex(9).draggable(true);
		
		if(pointList.size() >= 2  && pointList.size() <= 1000){
			polyline = new PolylineOptions().width(10).color(Color.RED).points(pointList);
		}
		
		addMarker();
		
	}
呼叫showRealtimeTrack方法,不斷的將採集到的使用者位置點增加到實體佇列中,不斷的重畫出線路點,重畫點需要呼叫drawRealtimePoint方法。

最後,在重畫完成之後,將重畫的點展示出來,呼叫addMarker方法,該方法的詳細內容如下:

	private void addMarker(){
		
		if(msUpdate != null){
			baiduMap.setMapStatus(msUpdate);
		}
		
		if(polyline != null){
			baiduMap.addOverlay(polyline);
		}
		
		if(overlay != null){
			baiduMap.addOverlay(overlay);
		}
		
	}
不斷的重新整理地圖的狀態,重新整理結束之後將座標點圖片和線路覆蓋上去,形成整個介面。

第六步:最後一步,增加user-permission,提升系統的許可權。

    <!-- 這個許可權用於進行網路定位-->
	<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" />