先說正常情況下,不需要 API key 就可以使用 Google Map API 的條件(不需要 API key 的意思是你不提供 key 或 key 亂寫都沒關係)。首先就是在 Google 自已的網頁當然不用 Key 就可以用,還有像是在 googlepages, iGoogle (如 Gadget 開發), orkut 上使用 Google Map API 也都不用 API key。再來,如果單純只是要在本機上試用 Google Map API 並不需要去申請 API Key,像是你用檔案的方式去開起來看、或是自己架 web server 連到 localhost 測試也不用 key 就可以使用。
一般如果是在靜態頁面上使用 Google Map API,申請 API key 並不是什麼麻煩的事,但像是 blog 之類的網頁,除非只出現在首頁側邊欄,不然如果是放在文中,因為 GMap API key 是根據你的網址(包括目錄)來申請,一般 blog 系統都會有多種不同的方式連到同一個內容,而會造成網址不同而無法使用。再來就是一些為網站加上內容的工具,例如想在相簿網站中依相片位置來顯示地圖,因為一般相簿網站不太可能把相片放於同一層網址中,所以在 key 的申請上也會造成困難。對於這個問題的解決一種是使用 iframe 內嵌另一個正確的網頁進來,基本上這的確可以解決不同網址的問題,但內嵌 iframe 就比較難和外層的網頁互動,如果只是單純顯示地圖就還沒問題,如果要有更具互動的操作就困難了。當然會去研究解法也是因為 Flickr Gmap Show 要在 flickr 上顯示 Google Map 的關係。
Google Map 本來就是幾乎都是 client 端 JavaScript 的程式,Server 端主要就是提供地圖的圖片資料,所以連驗證 API key 的動作其實也是在 client 端進行的,當然我們就有機會可以略過驗證的步驟了。GMap API 是使用下面的方式載入所需要的 JavaScript 程式:
<script type="text/javascript" src="http://maps.google.com/maps?file=api&v=2.x&key=abcdefg"> </script>既然是 JavaScript,我們當然可以老實不客氣的仔細看看到底是怎麼做的。這段程式 (以下稱 maps.js) 只是用以載入完整 Google Map 程式 (以下稱 main.js) 的 loader,還有和地區及文字相關的變數定義。因為 Google 會根據使用者所用的語言及提供的 api key 不同,而回傳不同的 JavaScript 程式,以保持主要程式 main.js 的部分不需改變,所以 Google 用這種兩段式的載入方式。我們要找的驗證的程式叫
GValidateKey,是定義在 main.js,但呼叫的動作是寫在 maps.js 裡: if (!GValidateKey("23b24975f9882203f0465f6c91adfee1b55adb98")) {
G_INCOMPAT = true;
alert("此網站上使用的 Google 地圖 API 機碼已由另一個網站註冊。....");
return;
}
GValidateKey 傳入的數字是由我們提供的 API key 所對應的網址所算出的 hash 值,而這個函式的驗證就是根據我們實際連線的網址計算一次 hash 再和這個值做比對。而這段程式被呼叫的流程是 maps.js 載入後,呼叫 GLoadMapsScript,GLoadMapsScript 會載入 main.js ,而 main.js 載入後會呼叫 maps.js 裡的 GLoad,而 GLoad 就會呼叫 GValidateKey 進行驗證。所以想要略過驗證的動作,就是要想辦法改掉這段驗證的程式。最簡單的改法,就是改出一份跳過不做 GValidateKey 的 maps.js,然後就可以爽爽的用了。修改過後的 maps.js 可以參考 http://www.wctang.info/maps.js,唯一做的修改就是不去呼叫 GValidateKey 。使用範例可以參考 http://www.wctang.info/maptest.html。 基本上,上面的做法已經可以達到我們想要的效果,就是在不論哪個網頁都可以使用 Google Map API。但這個做法有個缺點,因為地區及文字訊息都集中記錄在 maps.js,原本 Google 會根據 browser 所設定的語系而回傳適當語系的 maps.js,所以同一分 Google Map 程式我們看是中文訊息,外國人看就是英文訊息,而因為我們是用自己修改的 maps.js,所以除非我們能架起一個 Server 也可以回傳多種語系、修改過後的 maps.js,不然就會失去這多語系的功能。而且 Google Map 不時也會進行更新,用自己修改的 maps.js 也會讓 Google Map 的更新無法反應出來。要解決這個問題,一個就是也架個能即時修改並回傳正確修改後 maps.js 的 server ,另一個還是在 client 端下手,先從 google 端 load 正確的 maps.js,再動態去修改呼叫
GValidateKey 的部份。第二個作法就是要想辦法改變上述的流程,一樣先載入 maps.js,呼叫 GLoadMapsScript,而在 GLoadMapsScript 載入 main.js 之前,先去修改 GLoad 呼叫 GValidateKey 的程式,而後再去載入 main.js,而之後的流程就沒問題了。修改的方法就是在載入 google maps.js 前定義下面這段程式: <script type="text/javascript">
document.oldwrite = document.write;
document.write = function(str) {
if(document.oldwrite && window.GLoad && (typeof window.GLoad == 'function')) {
eval('var gloadstr=window.GLoad.toString(); gloadstr=gloadstr.replace(/\\n/,""); gloadstr=gloadstr.replace(/^\\s*function\\s*GLoad\\s*\\(\\)\\s*{/,""); gloadstr=gloadstr.replace(/}\\s*$/,""); gloadstr=gloadstr.replace(/GValidateKey\\("\w*"\\)/,"true"); window.GLoad=new Function(gloadstr);');
document.write=document.oldwrite;
}
document.oldwrite(str);
};
</script>
範例程式可以參考 http://www.wctang.info/maptest2.html。 以上的改法都有一個限制,就是不能使用 Geocoder 的功能,原因是因為使用 Geocoder 就是要連到 Google 去做查詢,而現在 Google 在做 Geocode 查詢時會在 Server 端做 API key 的檢查,這個就躲不掉了,我這種偷吃步在查詢時都會被打回票的。
呃,不知道這樣搞有沒有違反什麼使用條款,Google 目前對 Google Map 基本的使用是沒有呼叫次數的限制,而 Geocode 查詢是每天有 50000 次的限制,說不定哪天 Google 放寬這個限制後,就可以不用 API key 去查 Geocode 了...。
Update: 有關上述 Geocode 的問題請參考: Use Google Map Geocoder without API key
0 comments:
Post a Comment