2011年10月21日 星期五

[Android] javascript injection in WebView

上次寫了一篇"startActivityForResult and callback in WebView", 本篇則是上次這篇的延伸應用, 這是有人問我如何inject一整個javascript file到一個web page內(剛剛回顧了一下自己這篇, 發現我把它叫做javascript injection)

其實原理是一樣的, 在載入完原本的web page之後, 一樣透過URL來插入script:

mWebView.loadUrl("javascript:var js = document.createElement('script');js.type = 'text/javascript';js.src = 'http://my_host/1.js';document.getElementsByTagName('head')[0].appendChild(js);");

一樣是透過"javascript:"來inject, 不一樣的只是, 這次我要插入的是一整個js檔, 所以這串javascript的目的就是要建立一個新的script element, 並將它插入head裡, 這樣任務就達成了

但這方法的缺點是, 來源必須是一個url, 也就是要把script file放在server才可以, 如果script是來自應用程式本身, 比如說放在應用程式apk裡面, 或是放在data partition就不行了

在Honeycomb之前的版本, 我還沒想到一個比較好的解法, 但Honeycomb (API level 11, 含11)之後就有一個比較簡單的解法了

作法就是overwrite WebViewClient的shouldInterceptRequest,這似乎就是為了類似的用途而生的呀~~

這邊我將來自於apk asset目錄裡的檔案的url定義成"asset://", 因此, 想當然耳, 要導向的url就是這種, 作法也很簡單, 將asset的input stream包裝成WebResourceResponse就可以了, 這樣只要"js.src="後面的url是"asset://xxx.js", 這js的來源就是apk裡的asset

缺點是, 這方法只適用API level 11之後

延伸應用? 其實應該可以利用這個API做出一個lightweight版本的client side serlvet (這樣叫好像也不是很貼切, 反正就是不需要透過http去存取), 不過因為資訊只有url可以使用, 因此不能implement "POST"...

 

題外話, 這個我是在Ice cream sandwich的emulator上測試的, 不過真的要小抱怨一下, 開個emulator要開很久, 看篇漫畫結束後還沒跑完, 如果叫developer完全用emulator開發, 真的會抓狂吧....這樣開發者的開發意願也會降低吧.... = ="