想半天標題不知道怎下, 有點不是很貼切, 內容也寫的有點懶 :P 有可能會看不懂吧
最近開始想要一個禮拜想一個東西來實踐一下(不知道可以持續多久:P), 這禮拜想到的是這個: 從WebView內的javascript去叫起一個Activity, 然後把這Activity回傳的結果回傳給WebView內的javascript
具體的假想應用範例: import contact information, 從Javascript內叫contact picker, 並把所選的contact資訊匯入WebView內的form中
首先, 呼叫contact picker的範例如下:
public void launch()
{
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT);
}
基本上, 是要使用startActivityForResult, 這樣才能把所選定的contact給回傳給我們的Activity
但如何讓這lauch被javascript call到呢? 我們必須把這個method封裝到一個class內, 我用一個名叫ContactLauncher的class來做封裝, 並且將這個interface指定給WebView:
webView.addJavascriptInterface(new ContactLauncher(), "contactPicker");
這樣一來, 我們在javascript內就有一個contactPicker可以供呼叫了, javascript的範例如下:
function launchPicker()
{
if(contactPicker) {
//register callback
window.activitycallback = function(response) {
$('#name').val(response.name);
};
//call picker
contactPicker.launch();
} else { //no picker }
}
我們可以在javascript內透過"contactPicker.launch()"來叫起Contact picker, 這個就會直接呼叫ContactLauncher裡的lauch()
那在這之前的程式碼是幹啥用的呢? 由於launch()並不是一個blocking call, 並不會等到結果回傳後才結束, 而我們又要startActivityForResult回傳回來的資料, 因此我們需要一個callback來接收回傳的資料
那怎讓javascript可以接收回傳回來後的資料呢, 這邊我利用一個類似javascript injection的方式來做(原理是利用WebView可以接收"javascript:"這種形態的url)
以下是onActivityResult的實作 (這邊偷懶只取一個Display name):
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == PICK_CONTACT) { Cursor c = managedQuery(data.getData(), null, null, null, null); c.moveToNext(); String name = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); String json = "{name:'"+name+"'}"; webView.loadUrl("javascript:window.activitycallback("+json+");"); } }
因為在WebView內的那個javascript page我已經先安插了一個activitycallback, 所以就利用loadUrl來呼叫它, 這樣就大功告成了!
這只是一個簡單的範例, 還可以做的更generic一點, 比如說把傳入的資料轉化成json這段, 這招應該還可以做一些應用才對