Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 開發入門 >> 在 Android 上使用 XML 和 JSON,第 2 部分: 交付混合了 JSON 的 Android 應用程序(二)

在 Android 上使用 XML 和 JSON,第 2 部分: 交付混合了 JSON 的 Android 應用程序(二)

日期:2016/3/13 17:13:28      編輯:開發入門

連接 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>&nbsp;&nbsp;
<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 數組
解析從 JavaScript 發送來的 JSON 數組的屏幕截圖 
 

本例只存儲字符串數據,所以您可以簡單地將之附加到一個較長的字符串後面,並調用 CalculatorHandler 中的一個簡單函數,然後該函數可以將之解析出來。但是,若是應用程序想要跟蹤其他數據(比如某些變量的值)或者甚至試圖通過記錄特定的函數調用過程來剖析代碼,那麼情況又是如何呢?顯然,在較復雜的情景中,記錄和交換對象的能力很重要。


結束語

本系列其他文章

  • 在 Android 上使用 XML 和 JSON,第 1 部分:在 android 應用程序上研究 JSON 和 XML 益處

本文演示了 android 應用程序中的 Java 代碼與 WebVIEw 中的 JavaScript 代碼之間傳輸數據的技術,以及利用 WebKit 開發的混合應用程序的一些比較普通的主題。混合應用程序混合了 Javascript、JSON、回調函數、android-SDK Java 代碼以及所有當中最為重要的成份 — 想象力,以交付靈活且功能強大的移動應用程序。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved