編輯:開發入門
連接 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 代碼以及所有當中最為重要的成份 — 想象力,以交付靈活且功能強大的移動應用程序。
第一個Android的應用程序:“Hello, Android!”
作為開發者,你的第一感覺是你拿到這個開發框架寫“Hello, World!”程序時的難易程度給你留下的。 當然,在android裡,這個非常容易,下面我給你演
Android 輕松實現語音識別
所以Google Voice Recognition在android 的實現就變得極其輕松。語音識別,借助於雲端技術可以識別用戶的語音輸入,包括語音控制等技術,下面我們
android中點中overlay彈出帶尾巴的氣泡的實現
就是上面的樣子做這個過程中我碰到兩個問題:1:如何做帶尾巴的氣泡VIEw2:如何把這個View添加到MapVIEw中.1:如何做帶尾巴的氣泡VIEw我是采用背景圖的方式
智能交通之路(二)
City-Go-RoundCity-Go-Round Web 站點在 2009 年 12 月在線推出(見 參考資料)。除了作為一個開放式交通數據 — 正如它所