1. 程式人生 > >百度地圖開發(四)之POI檢索

百度地圖開發(四)之POI檢索

POI檢索

    POI~~~ Point of Interest,翻譯過來就是“興趣點”。我們在使用地圖的時候,搜尋周邊的ktv,飯店,或者賓館的時候,輸入關鍵字,然後地圖展示給我們很多個點,這些點就是我需要的資訊。這就是所謂的興趣點,也就是一個普通的查詢,然後結果的反饋罷了。

    百度地圖SDK提供了三種類型的POI檢索:周邊檢索、區域檢索和城市內檢索。

    還是從API看起。找到com.baidu.mapapi.search.poi程式包:


    看到這個包中有一個回撥介面,用於接收檢索結果;PoiSearch類用於檢索請求;PoiResult類表示搜尋結果,相比它應該在OnGetPoiSearchResultListener這個介面的某個函式中最為引數~~

最後還有4個xxxOption引數類,分別對應周邊檢索、城市內檢索、區域檢索、poi詳情檢索。

    PoiSearch :POI檢索介面,是我們應該重點關注的類。


    從api中可以看出,此類是一個靜態類,構造方法被私有化處理,只能通過newInstance()獲得例項。看到它的方法,就發現正好有4個方法對應上面四個檢索引數類。

名稱 方法 引數
範圍檢索 searchInBound() PoiBoundSearchOption
城市內檢索 searchInCity() PoiCitySearchOption
周邊檢索 searchInNearby() PoiNearbySearchOption
詳情檢索 searchPoiDetail() PoiDetailSearchOption

    實際上,詳情檢索與其他三種類型不算一類,它是在通過其他三種檢索型別得到的結果在去查詢得到詳細的資訊。

    通過這幾個類可以對不同的型別設定檢索引數,下面看一下監聽介面:


    該介面有兩個回撥函式,一個用於接收返回的poi查詢結果,一個用於接收返回的詳情查詢結果。而結果分別封裝在PoiResult和PoiDetailResult這兩個類中了。

    PoiResult:

    

    從這裡可以看出,百度對檢索結果進行了分頁處理。所以在設定引數的時候,需要設定單頁容量和頁號。

// 例項化PoiSearch物件
		poiSearch = PoiSearch.newInstance();
		// 設定檢索監聽器
		poiSearch.setOnGetPoiSearchResultListener(poiSearchListener);
/**
	 * POI檢索監聽器
	 */
	OnGetPoiSearchResultListener poiSearchListener = new OnGetPoiSearchResultListener() {
		@Override
		public void onGetPoiResult(PoiResult poiResult) {
			if (poiResult == null
					|| poiResult.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {// 沒有找到檢索結果
				Toast.makeText(PoiSearchActivity.this, "未找到結果",
						Toast.LENGTH_LONG).show();
				return;
			}

			if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {// 檢索結果正常返回
				bdMap.clear();
				MyPoiOverlay poiOverlay = new MyPoiOverlay(bdMap);
				poiOverlay.setData(poiResult);// 設定POI資料
				bdMap.setOnMarkerClickListener(poiOverlay);
				poiOverlay.addToMap();// 將所有的overlay新增到地圖上
				poiOverlay.zoomToSpan();
				//
				totalPage = poiResult.getTotalPageNum();// 獲取總分頁數
				Toast.makeText(
						PoiSearchActivity.this,
						"總共查到" + poiResult.getTotalPoiNum() + "個興趣點, 分為"
								+ totalPage + "頁", Toast.LENGTH_SHORT).show();

			}
		}
/**
	 * 城市內搜尋
	 */
	private void citySearch(int page) {
		// 設定檢索引數
		PoiCitySearchOption citySearchOption = new PoiCitySearchOption();
		citySearchOption.city(editCityEt.getText().toString());// 城市
		citySearchOption.keyword(editSearchKeyEt.getText().toString());// 關鍵字
		citySearchOption.pageCapacity(15);// 預設每頁10條
		citySearchOption.pageNum(page);// 分頁編號
		// 發起檢索請求
		poiSearch.searchInCity(citySearchOption);
	}

	/**
	 * 範圍檢索
	 */
	private void boundSearch(int page) {
		PoiBoundSearchOption boundSearchOption = new PoiBoundSearchOption();
		LatLng southwest = new LatLng(latitude - 0.01, longitude - 0.012);// 西南
		LatLng northeast = new LatLng(latitude + 0.01, longitude + 0.012);// 東北
		LatLngBounds bounds = new LatLngBounds.Builder().include(southwest)
				.include(northeast).build();// 得到一個地理範圍物件
		boundSearchOption.bound(bounds);// 設定poi檢索範圍
		boundSearchOption.keyword(editSearchKeyEt.getText().toString());// 檢索關鍵字
		boundSearchOption.pageNum(page);
		poiSearch.searchInBound(boundSearchOption);// 發起poi範圍檢索請求
	}

	/**
	 * 附近檢索
	 */
	private void nearbySearch(int page) {
		PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption();
		nearbySearchOption.location(new LatLng(latitude, longitude));
		nearbySearchOption.keyword(editSearchKeyEt.getText().toString());
		nearbySearchOption.radius(1000);// 檢索半徑,單位是米
		nearbySearchOption.pageNum(page);
		poiSearch.searchNearby(nearbySearchOption);// 發起附近檢索請求
	}
    通過以上程式碼,就可以完成三種類型的檢索,分組的時候只不過是改一下pageNum()引數。

    查詢出這一組組的結果之後,可以通過新增覆蓋物的方式顯示在地圖上。但是如果按照之前的新增覆蓋物的方式進行新增的話,需要在得到的List<PoiInfo>中得到經緯度資料,然後迴圈構造出覆蓋物物件,新增到地圖上。

這樣做未嘗不可,但是百度提供了更簡便的方式給我們。

    開啟com.baidu.mapapi.overlayutil這個包,看到有一個類用於顯示poi的overlay。

        
    從api中得知,該類已經實現了marker點選事件的介面了。我們在介面的毀掉函式onGetPoiResult()中得到了PoiResult物件,然後可以通過setData(PoiResult poiResult)這個方法設定poi資料顯示在地圖上。
API中說明onPoiClick(int i)可以覆寫,這樣我們可覆寫此方法,當點選底圖上覆蓋物的時候查詢POI詳細資訊。

class MyPoiOverlay extends PoiOverlay {
		public MyPoiOverlay(BaiduMap arg0) {
			super(arg0);
		}
		@Override
		public boolean onPoiClick(int arg0) {
			super.onPoiClick(arg0);
			PoiInfo poiInfo = getPoiResult().getAllPoi().get(arg0);
			// 檢索poi詳細資訊
			poiSearch.searchPoiDetail(new PoiDetailSearchOption()
					.poiUid(poiInfo.uid));
			return true;
		}
	}
    PoiOverlay從OverlayManager這個類中繼承了:

1. addToMap() -- 將所有overlay新增到地圖上

2. removeFromMap() -- 將所有overlay從地圖上移除

3. zoomToSpan() -- 縮放地圖,使所有overlay都在合適的視野內

這樣可以在返回poi結果的時候,把poi標註在地圖上了:

if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {// 檢索結果正常返回
	bdMap.clear();
	MyPoiOverlay poiOverlay = new MyPoiOverlay(bdMap);
	poiOverlay.setData(poiResult);// 設定POI資料
	bdMap.setOnMarkerClickListener(poiOverlay);
	poiOverlay.addToMap();// 將所有的overlay新增到地圖上
	poiOverlay.zoomToSpan();
	//
	totalPage = poiResult.getTotalPageNum();// 獲取總分頁數
	Toast.makeText(
			PoiSearchActivity.this,
			"總共查到" + poiResult.getTotalPoiNum() + "個興趣點, 分為"
					+ totalPage + "頁", Toast.LENGTH_SHORT).show();
}
當我們點選一個覆蓋物的時候,去查詢詳細資訊:
@Override
		public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
			if (poiDetailResult.error != SearchResult.ERRORNO.NO_ERROR) {
				Toast.makeText(PoiSearchActivity.this, "抱歉,未找到結果",
						Toast.LENGTH_SHORT).show();
			} else {// 正常返回結果的時候,此處可以獲得很多相關資訊
				Toast.makeText(
						PoiSearchActivity.this,
						poiDetailResult.getName() + ": "
								+ poiDetailResult.getAddress(),
						Toast.LENGTH_LONG).show();
			}
		}

短串分享

    短串分享時指:使用者查詢得到的地理位置對應到一個url連結地址,百度將這種地址做短了,就俗稱短串。我們可以把這個短傳通過簡訊、郵箱或者第三方分享給其他使用者,當其他使用者可以點選短串可以開啟手機上的百度地圖客戶端或者手機瀏覽器進行檢視。
    目前短串分享開放了【poi搜尋結果分享】和【反向地理編碼結果分享】。

    開啟com.baidu.mapapi.search.share這個包:


    我們看到這個包結構與POI的包結構非常相似。按照之前的經驗,可以猜想:ShareUrlSearch是用來發起短串檢索請求的;2個xxxOption()方法用來對不同的請求型別設定引數的;onGetShareUrlResultListener是用來監聽返回結果的;ShareUrlShare就是返回結果的包裝類。

// 例項化共享URL查詢介面物件
		shareUrlSearch = ShareUrlSearch.newInstance();
		// 設定共享URL結果監聽函式
		shareUrlSearch.setOnGetShareUrlResultListener(shareUrlResultListener);

/**
	 * 短串檢索監聽器
	 */
	OnGetShareUrlResultListener shareUrlResultListener = new OnGetShareUrlResultListener() {

		@Override
		public void onGetPoiDetailShareUrlResult(ShareUrlResult shareUrlResult) {
			if (shareUrlResult.error != SearchResult.ERRORNO.NO_ERROR) {
				Toast.makeText(PoiSearchActivity.this, "抱歉,未搜尋到短串",
						Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(PoiSearchActivity.this, "poi詳情分享url:" + shareUrlResult.getUrl(),
						Toast.LENGTH_LONG).show();
			}
		}

		@Override
		public void onGetLocationShareUrlResult(ShareUrlResult shareUrlResult) {
			if (shareUrlResult.error != SearchResult.ERRORNO.NO_ERROR) {
				Toast.makeText(PoiSearchActivity.this, "抱歉,未搜尋到短串",
						Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(PoiSearchActivity.this,  "請求位置資訊分享url:" + shareUrlResult.getUrl(),
						Toast.LENGTH_LONG).show();
			}
		}
	};
發起請求:
// 請求位置資訊分享URL
			shareUrlSearch.requestLocationShareUrl(new LocationShareURLOption()
					.location(poiInfo.location).name("共享點名稱").snippet("123"));
			// 共享點位置 --- 共享點名稱 --- 通過短URL調起客戶端時作為附加資訊顯示在名稱下面

			//請求poi詳情分享URL的時候引數xxxOption中只有一個uid
			shareUrlSearch
					.requestPoiDetailShareUrl(new PoiDetailShareURLOption()
							.poiUid(poiInfo.uid));

線上建議查詢

    指根據關鍵詞查詢線上建議詞。


    實現方式與短串分享大同小異。程式碼就略了吧~~~

下載:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

百度地圖開發(二)之新增覆蓋物+地理編碼和反地理編碼: