編輯:開發入門
連接 JavaScript 接口
下一步是啟用 Activity 中的 Java 代碼,以與 WebVIEw 管理的 Html 文件中的 JavaScript 代碼交互。這是通過調用addJavascriptInterface()
方法完成的,如 清單 4 所示。
該函數的參數是一個 Java 類的實例和一個名稱空間標識符。例如,對於這個應用程序,您定義一個 calc
名稱空間,並實現名為CalculatorHandler
的類中的代碼,如 清單 5 所示。
清單 5. CalculatorHandler
實現
// Javascript handler final class CalculatorHandler { private int iterations = 0; // write to LogCat (Info) public void Info(String str) { iterations++; Log.i("Calc",str); } // write to LogCat (Error) public void Error(String str) { iterations++; Log.e("Calc",str); } // sample to retrIEve a custom - written function with the details provided // by the android native application code public String GetSomeFunction() { iterations++; return "var q = 6;function dynamicFunc(v) { return v + q; }"; } // Kill the app public void EndApp() { iterations++; finish(); } public void setAnswer(String a) { iterations++; Log.i(tag,"Answer [" + a + "]"); } public int getIterations() { return iterations; } public void SendHistory(String s) { Log.i("Calc","SendHistory" + s); try { JSONArray ja = new JSONArray(s); for (int i=0;i<ja.length();i++) { Log.i("Calc","History entry #" + (i+1) + " is [" + ja.getString(i) + "]"); } } catch (Exception ee) { Log.e("Calc",ee.getMessage()); } } }
在 JavaScript 環境中,通過 window.calc.methodname
語法訪問CalculatorHandler
的方法。例如,CalculatorHandler
實現一個名為 Info()
的方法,後者接受一個字符串參數並將之寫到應用程序日志中。要從 JavaScript 環境訪問此方法,可使用類似這樣的語法:window.calc.Info("write this string to the application log!");
。
基本了解了如何從 Javascript 代碼調用 Java 代碼之後,我們再來看 清單 6 中的 index.Html 文件,看各種方法是如何被調用的。
清單 6. WebVIEw 控件中呈現(和執行)的 index.Html
<Html> <head> <meta name="vIEwport" content="width=device-width,initial-scale=0.25, user-scalable=yes" /> <title>android to Javascript with JSON</title> </head> <script language="JavaScript"> var cmdHistory = new Array(); function startup() { try { window.calc.Info("Starting up...."); cmdHistory[cmdHistory.length] = "startup"; } catch (ee) { } } function PerformSimpleCalculation(formula) { try { cmdHistory[cmdHistory.length] = "PerformSimpleCalculation"; var answer = eval(String(formula)); document.getElementById('data').value = answer; window.calc.setAnswer(answer); } catch (ee) { window.calc.Error(ee); } } function PerformComplexCalculation(andmethod) { try { /* * argument to this function is a single object with 2 "members or properties" * operation: this is a string naming what we want the function to do. * array of arguments: this is an array of integers * */ //alert(andmethod.operation); //alert(andmethod.arguments.length); if (andmethod.operation == "addarray") { cmdHistory[cmdHistory.length] = "PerformCompleCalculation-addarray"; var i; var result = 0; for (i=0;i<andmethod.arguments.length;i++) { result += andmethod.arguments[i]; } document.getElementById('data').value = result; window.calc.setAnswer(result); } if (andmethod.Operation == "multarray") { cmdHistory[cmdHistory.length] = "PerformCompleCalculation-multarray"; var i; var result = 1; for (i=0;i<andmethod.arguments.length;i++) { result *= andmethod.arguments[i]; } document.getElementById('data').value = result; window.calc.setAnswer(result); } } catch (ee) { window.calc.Error(ee); } } function dynamicfunction() { try { cmdHistory[cmdHistory.length] = "PerformCompleCalculation-dynamic"; eval(String(window.calc.GetSomeFunction())); var result = dynamicFunc(parseInt(document.getElementById('data').value)); document.getElementById('data').value = result; }catch (ee) { alert(ee); } } </script> <body > <center> <h3>Running in Web VIEw :)</h3> this is some sample text here <br /> <input type="text" id="data" value="starting value"><br /> <button onclick="window.calc.Info(document.getElementById('data').value);">Log Info</button> <button onclick="window.calc.Error(document.getElementById('data').value);">Log Error</button><br /> <button onclick="dynamicfunction();">Dynamic</button> <button onclick="alert(String(window.calc.getIterations()));">How Many Calls</button> <button onclick="window.calc.SendHistory(JSON.stringify(cmdHistory));"> History</button> <button onclick="if (window.confirm('End App?')) window.calc.EndApp();">Kill This App</button><br /> </center> </body> </Html>
仔細研究一下 清單 6 末尾的按鈕處理程序。基本上,這些按鈕處理程序都調用 window.calc
名稱空間中的方法,這些方法在 androidJSON.Java 中的 CalculatorHandler
類中實現。
清單 5 和 清單 6 協同工作,演示了 Javascript 環境中初始化的和 Java 源文件中實現的代碼交互。但是如何從 Activity 代碼中初始化一些您想要在 WebVIEw 中發生的動作呢?
現在應該更深入地來看 Java 代碼了。
插入 JavaScript 代碼
從將一個數學公式傳遞到 Javascript 代碼進行計算這樣一個任務開始。JavaScript 最偉大(也最危險)的特性之一是 eval()
函數。eval()
函數允許字符串代碼的運行時計算。在本例中,您從 EditText 控件接受一個字符串並傳遞到 JavaScript 環境進行計算。具體來說,我們調用 清單 6 中的PerformSimpleCalculation()
函數。
清單 7 包含 androidJSON.Java 中的代碼,它負責處理按鈕選擇。
清單 7. 從 Java 調用 PerformSimpleCalculation()
JavaScript 函數
btnSimple.setOnClickListener(new OnClickListener() { public void onClick(VIEw v) { Log.i(tag,"onClick Simple"); // Perform action on click try { String formulaText = formula.getText().toString(); Log.i(tag,"Formula is [" + formulaText + "]" ); browser.loadUrl("Javascript:PerformSimpleCalculation(" + formulaText + ");"); } catch (Exception e) { Log.e(tag,"Error ..." + e.getMessage()); } } });
不管此方法有多少行,這裡唯一要關注的是 browser.loadurl()
行,它傳遞一個格式字符串:Javascript:<code to execute>
。
此 Javascript 代碼被注入到 WebView 的當前頁面並執行。這樣,Java 代碼就可以執行 WebVIEw 中定義的 JavaScript 代碼了。
在 Simple 例子中,傳遞了一個字符串。但是,當需要處理更復雜的結構時該怎麼辦呢?這就是 JSON 可派上用場的地方。清單 8 展示了 PerformComplexCalculation()
函數的調用,該函數參見 清單 6。
清單 8. 通過傳遞一個 JSON 對象調用更復雜的函數
btnComplex.setOnClickListener(new OnClickListener() { public void onClick(VIEw v) { Log.i(tag,"onClick Complex"); // Perform action on click try { String jsonText = ""; if (flipflop == 0) { jsonText = "{ \"operation\" : \"addarray\",\"arguments\" : [1,2,3,4,5,6,7,8,9,10]}"; flipflop = 1; } else { jsonText = "{ \"Operation\" : \"multarray\",\"arguments\" : [1,2,3,4,5,6,7,8,9,10]}"; flipflop = 0; } Log.i(tag,"jsonText is [" + JSonText + "]" ); browser.loadUrl("Javascript:PerformComplexCalculation(" + JSonText + ");"); } catch (Exception e) { Log.e(tag,"Error ..." + e.getMessage()); } } });
研究一下 清單 6 中的 JavaScript 函數PerformComplexCalculation
。注意,傳遞進來的參數不是字符串,而是您自己創建的一個對象。
Operation
- 要處理的函數或過程的名稱arguments
- 這是一個整數數組對象只包含兩個屬性,但是完全可以更復雜,以滿足更高的需求。在本例中,PerformComplexCalculation()
JavaScript 函數支持兩種不同的操作:addarray 和 multarray。當這些操作在調用時完成其工作時,通過調用函數 window.calc.setAnswer
,將結果傳遞回 Java 代碼。這裡,您看到了 Java 和 JavaScript 代碼之間的雙向數據流。
在本例中,您傳遞了一個 JSON 對象,但是得到的一條經驗是,在處理從 Java 代碼返回來的 Java 字符串時,它有助於將它們轉換成 JavaScript 字符串。這可以像本例中一樣通過將值傳遞給 String 函數來做到:eval(String(formula));
。
JavaScript eval()
函數使用 JavaScript 字符串。無需轉換的話,eval
函數基本上不做任何事情。
對於一個稍微復雜一點的例子,鼓勵您好好看一下 Dynamic 按鈕在 WebVIEw 中被選中時的代碼段。
要完成代碼例子,來看一下將一個字符串數組從 Javascript 環境傳遞到 Java 環境。
回頁首
交換 JSON 對象
示例應用程序 (index.Html) 中的 JavaScript 代碼將本地函數調用記錄到一個名為 cmdHistory
的頁面級別數組中。每次調用函數時,您都將一個新條目添加到該數組中。例如,當 dynamicfunction()
被調用時,一個新的字符串被存儲:cmdHistory[cmdHistory.length] = "PerformCompleCalculation-dynamic";
。
關於此方法,沒有什麼特別的地方;它只是一個在頁面級別收集使用數據的例子。也許該數據存儲在 android 應用程序的數據庫中會有用。此數據如何回到 Java 代碼呢?
要發送字符串對象數組,您調用 JSON.stringify
函數,將數組作為參數傳遞進來。根據需要,stringify 函數可以允許定制一個復雜對象的特定屬性如何被格式化。關於這是如何完成的更多信息,可以參考 JSon.org 中的解釋(參見 參考資料)。
圖 3 展示了應用程序的典型運行中解析 JSON 數組之後 Log 中的內容。
圖 3. 解析從 JavaScript 發送來的 JSON 數組
本例只存儲字符串數據,所以您可以簡單地將之附加到一個較長的字符串後面,並調用 CalculatorHandler
中的一個簡單函數,然後該函數可以將之解析出來。但是,若是應用程序想要跟蹤其他數據(比如某些變量的值)或者甚至試圖通過記錄特定的函數調用過程來剖析代碼,那麼情況又是如何呢?顯然,在較復雜的情景中,記錄和交換對象的能力很重要。
結束語
本文演示了 android 應用程序中的 Java 代碼與 WebVIEw 中的 JavaScript 代碼之間傳輸數據的技術,以及利用 WebKit 開發的混合應用程序的一些比較普通的主題。混合應用程序混合了 Javascript、JSON、回調函數、android-SDK Java 代碼以及所有當中最為重要的成份 — 想象力,以交付靈活且功能強大的移動應用程序。
作為開發者,你的第一感覺是你拿到這個開發框架寫“Hello, World!”程序時的難易程度給你留下的。 當然,在android裡,這個非常容易,下面我給你演
所以Google Voice Recognition在android 的實現就變得極其輕松。語音識別,借助於雲端技術可以識別用戶的語音輸入,包括語音控制等技術,下面我們
就是上面的樣子做這個過程中我碰到兩個問題:1:如何做帶尾巴的氣泡VIEw2:如何把這個View添加到MapVIEw中.1:如何做帶尾巴的氣泡VIEw我是采用背景圖的方式
City-Go-RoundCity-Go-Round Web 站點在 2009 年 12 月在線推出(見 參考資料)。除了作為一個開放式交通數據 — 正如它所