說起百度地圖,國人可是無人不知無人不曉的,就連幼童和老人都知道打開百度地圖來搜索目的地和導航路線,可見百度地圖在採集路網數據、更新路況實時情況上是多麼的準確和及時。
關於百度地圖的詳細講解,大家可以移步到百度百科,上面對其有詳細的說明。
![接入百度LBS服務的那些「坑」,你踩過嗎?](http://p2.ttnews.xyz/loading.gif)
作為國內第二大地圖廠商,百度地圖這幾年發展迅猛,在LBS服務上更是加快了前行的腳步,所以一些第三方公司為了加快自己在地圖和LBS方面的發展,都會選擇接入百度地圖、高德地圖或騰訊地圖的服務,這樣可以最簡單最快的深耕自己細分領域的業務,畢竟是「專業的人幹專業的事兒」。
![接入百度LBS服務的那些「坑」,你踩過嗎?](http://p2.ttnews.xyz/loading.gif)
首先先給一下百度地圖支持的接入服務全景圖,從前端H5,安卓和IOS SDK到後端的Web API一應俱全。本文主要講一下如何接入百度地圖服務,主要涉及到前端、後端(Java)的詳細配置,並以代碼來詳細介紹下後端接入百度地圖Web API的流程。
控制檯創建應用
用百度賬號登錄後,進入到百度地圖開發平臺的控制檯界面,在裡面點擊創建應用,就會彈出下圖中的頁面,填入應用名稱,選擇好自己的應用類型(
H5選瀏覽器端,Android選Android SDK,IOS選IOS SDK,服務端選服務端,微信小程序就選微信小程序),啟用服務會根據自己選的應用類型不同,動態展示出對應的服務項目,比如默認是服務端,下面就列出了服務端提供的服務列表。下面就是給個應用類型下,相對應的地圖服務項目,大家可以根據自己實際的業務需求選擇合適的服務項目。
創建好應用後,就可以在查看應用中看到新建好的應用,而且會給每個應用分配一個AK,用來控制訪問應用,但需要注意的是之前申請的AK是可以直接用來訪問應用中的API接口的,但現在百度升級了校驗機制後,需要再拿一個SK來做一下複雜的生產sn的過程,稍後我會詳細講解下代碼。
下面是我們項目中創建的應用,可以看出有安卓、iOS和Java後端,大家根據實際需求創建即可,當然每個項目都是收費的。
應用接入服務
下面我就以一個「地址檢索」的接口為例詳細說下Java後端如何接入地址服務。
1. 仔細查看後端API,確定「地址檢索」服務API是哪個?
經過確認,地址檢索的Web API接口為行政區劃區域檢索接口,姓名Url為:
http://api.map.baidu.com/place/v2/search?query=ATM機&tag=銀行®ion=北京&output=json&ak=您的ak //GET請求
2.關鍵參數說明
query:檢索的關鍵字;
region:檢索行政區劃區域,限制關鍵字的區域範圍;
output:輸出的數據格式,可以是json或xml;
ak:開發者的訪問密鑰;
sn:開發者的權限簽名;
3. 開發者權限簽名sn生成
創建完應用後,會給應用生成一個ak和一個sk,ak的作用大家也知道了,就是在請求的url上當做參數傳給服務端,但sk是幹什麼呢?最終請求百度API時需要的sn又是幹什麼的?是如何生成的呢?
sn就是signature簽名,是為了加強接口的安全性根據入參和sk的值動態計算出來的,這樣就增加了接口被刷的難度,提高了服務的併發性。
sn計算出來後,百度的服務會根據入參和sk也會自動計算出一個簽名,跟請求方傳過去的簽名比對,相等則提供服務,不相等咋拒絕服務,返回錯誤。
根據入參和sk計算sn的代碼:
public static String calSn(final String query, final String region, final String ak, final String sk) { // 計算sn跟參數對出現順序有關,get請求請使用LinkedHashMap保存,該方法根據key的插入順序排序; // post請使用TreeMap保存,該方法會自動將key按照字母a-z順序排序。 // 所以get請求可自定義參數順序(sn參數必須在最後)發送請求,但是post請求必須按照字母a-z順序填充body(sn參數必須在最後)。 // 以get請求為例:http://api.map.baidu.com/geocoder/v2/?address=百度大廈&output=json&ak=yourak,paramsMap中先放入address,再放output,然後放ak, // 放入順序必須跟get請求中對應參數的出現順序保持一致。 Map paramsMap = new LinkedHashMap(); paramsMap.put("query", query); paramsMap.put("region", region); paramsMap.put("output", "json"); paramsMap.put("ak", ak); // 調用下面的toQueryString方法,對LinkedHashMap內所有value作utf8編碼 String paramsStr = toQueryString(paramsMap); if (null == paramsStr) { return null; } // 拼接接口 String wholeStr = new String("/place/v2/search?" + paramsStr + sk); // 對上面wholeStr再作utf8編碼 String tempStr = null; try { tempStr = URLEncoder.encode(wholeStr, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } // 調用下面的MD5方法得到最後的sn簽名 return MD5(tempStr); }
對Map內所有value做UTF-8轉換,拼接後返回結果:
public static String toQueryString(Map, ?> data) { StringBuffer queryString = new StringBuffer(); try { for (Map.Entry, ?> pair : data.entrySet()) { queryString.append(pair.getKey() + "="); queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8") + "&"); } if (queryString.length() > 0) { queryString.deleteCharAt(queryString.length() - 1); } return queryString.toString(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; }
來自stackoverflow的MD5計算方法,調用了MessageDigest庫函數,並把byte數組結果轉換成16進制:
public static String MD5(String md5) { try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); byte[] array = md.digest(md5.getBytes()); StringBuffer sb = new StringBuffer(); for (int i = 0; i < array.length; ++i) { sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3)); } return sb.toString(); } catch (java.security.NoSuchAlgorithmException e) { } return null; }
4. 發送請求,調用百度API
拿著第三步生成的簽名,和之前的參數和ak,調用百度的Web API,返回結果。
其實就是個發送http請求的代碼,很簡單,具體如下:
整個調用流程就結束了,是不是非常簡單,但其實在寫代碼過程中有很多小坑,大家有興趣的試試就知道了。最後給大家一個返回值的截圖,JSON格式的很容易讀懂:
碼子不易,歡迎大家點贊關注,如果感興趣也歡迎留言討論。