`

Android 混合了 JSON 的 Android 应用程序

阅读更多
通过WebView在javascript里调用java 方法代码, 在java代码里执行javascript代码, 二者通过json进行数据交换

设置 WebView 小部件

// connect to our browser so we can manipulate it
browser = (WebView) findViewById(R.id.calculator);

// set a webview client to override the default functionality
browser.setWebViewClient(new wvClient());

// get settings so we can config our WebView instance
WebSettings settings = browser.getSettings();

// JavaScript?  Of course!
settings.setJavaScriptEnabled(true);

// clear cache
browser.clearCache(true);

// this is necessary for "alert()" to work
browser.setWebChromeClient(new WebChromeClient());

// add our custom functionality to the javascript environment
browser.addJavascriptInterface(new CalculatorHandler(), "calc");

// uncomment this if you want to use the webview as an invisible calculator!
//browser.setVisibility(View.INVISIBLE);

// load a page to get things started
browser.loadUrl("file:///android_asset/index.html");

// allows the control to receive focus
// on some versions of Android the webview doesn't handle input focus properly
// this seems to make things work with Android 2.1, but not 2.2
// browser.requestFocusFromTouch();



将一个名为 browser 的 Activity 范围变量捆绑到了 WebView 控件。WebView 是一个相当复杂的类,可高度定制。例如,您需要设置几个类,以得到与 web 浏览器相关的预期函数。这是程序员必须投入一定精力来得到一些有用函数的地方之一。但是,此定制是没有限制的。对于此应用程序的目的来说,WebView 控件已经进行了最低限度的部署。

WebViewClient 提供用于捕获各种事件的钩子,这些事件包括页面加载开始和结束、表单重新提交、键盘截取以及程序员喜欢跟踪并操纵的很多其他事件。类似地,您需要 WebChromeClient 的一个实例,用于允许诸如非常有用的 alert() JavaScript 函数之类的函数。使用 WebSettings 来为控件启用 JavaScript。


连接 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 中的解释
分享到:
评论

相关推荐

    JS调用Android方法,向Android方法传递json数据

    通过WebView,开发者可以在原生Android应用中嵌入HTML、CSS和JavaScript代码,从而构建混合式应用。 当需要在JavaScript和Android之间进行交互时,我们通常会用到`addJavascriptInterface()`方法。这个API允许我们...

    Android处理JSON数据-JSON数据解析.pdf

    在实际应用中,Android开发者通常会结合网络请求库如Retrofit或Volley来获取JSON数据,并使用Gson或Jackson等库进行自动映射到Java对象,以简化数据处理过程。同时,需要注意错误处理,确保在解析过程中能够正确处理...

    android与H5交互传参

    Android提供了WebView组件,它允许在应用程序中嵌入一个浏览器内核,从而展示网页内容。为了实现H5与Android的交互,我们需要利用WebView提供的`addJavascriptInterface()`方法。这个方法允许我们将Java对象暴露给...

    Android应用程序开发宝典

    《Android应用程序开发宝典》是一本专为开发者设计的指南,涵盖了在飞凌嵌入式公司的OK6410、FL6410以及TE6410开发板上进行Android应用开发的全面知识。这本书深入浅出地讲解了如何在这些硬件平台上构建、调试和优化...

    基于Android及JSON的“友农”APP设计与实现.pdf

    负载均衡采用Tomcat和Nginx代理服务器的混合模式,Tomcat负责JSON格式数据的解析,而Nginx则作为反向代理服务器,优化了网络请求的处理。 3. 前端交互与数据解析 前端与服务器之间的通信采用HTTP协议,通过JSONDUMP...

    Android js交互,含json数据,eventbus框架

    总的来说,理解Android与JavaScript的交互、JSON数据的传递以及EventBus的使用,对于提升Android应用的用户体验和代码质量至关重要。掌握这些技术,开发者可以更高效地构建功能丰富的混合式应用。

    Android中的JSON详细总结

    ### Android中的JSON详解 #### JSON概述 JSON(JavaScript Object Notation),是一种轻量级的数据交换格式,因...通过这些类,开发者可以在Android应用中高效地解析和生成JSON数据,从而实现数据的灵活交换和处理。

    Android开发_2年工作经验Android软件工程师求职简历个人简历.pdf

    Android 软件工程师是移动应用程序开发的核心人物,负责开发、测试和维护 Android 操作系统下的软件应用程序。为了成为一名合格的 Android 软件工程师,需要具备以下技术栈: 1. 数据存储方式:Android 提供了五种...

    Go-工具使用WebView从您的golanghttp服务器构建Android应用

    在本文中,我们将深入探讨如何使用Go语言以及特定的工具,如`gowebview`,来构建一个Android应用程序,该程序能够与您的Golang HTTP服务器进行交互。`gowebview`是一个开源项目,允许开发者使用Go语言创建原生的移动...

    Cordova(PhoneGap)Android Native混合开发值传递

    总的来说,Cordova(PhoneGap)Android混合开发中的值传递是一个复杂但灵活的过程,它需要理解JavaScript和Java的交互机制,以及如何利用Cordova提供的工具和API。通过熟练掌握这些技能,开发者可以构建出既具有Web...

    一个移动应用开发工具完全基于存储在JSON文件中的HTML创建App

    标题中的“一个移动应用开发工具完全基于存储在JSON文件中的HTML创建App”指的是使用特定的开发工具,通过将HTML内容存储在JSON文件中,来构建跨平台的移动应用程序。这种开发方式结合了JSON的结构化数据特性和HTML...

    android和js相互调用

    在Android和JavaScript交互的过程中,开发者经常需要在两者之间进行数据传递和方法调用,以便实现更复杂的混合式应用开发。这种技术通常应用于Webview环境,其中Android原生代码与嵌入的网页内容进行互动。本篇文章...

    android解析JSON数据

    在Android开发中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,广泛用于应用程序与服务器之间的数据传输。理解如何在Android中解析JSON数据是至关重要的,这将帮助开发者有效地处理从网络获取的...

    Android应用开发揭秘.rar

    《Android应用开发揭秘》这本书是Android开发者们的重要参考资料,它深入浅出地揭示了Android应用程序开发的各个环节。从基础知识到高级技巧,从架构设计到性能优化,覆盖了Android开发的全貌。 首先,Android应用...

    LearnJsonVSXML:了解android平台上Json和XML的区别

    本系列的其他文章第 2 部分:使用 JSON 交付混合 Android 应用程序 本文介绍了 Android 应用程序上下文中的 XML 和 JSON 数据交换格式。 与 JSON 方法相比,XML 方法速度更快,内存限制更少 - 代价是额外的复杂性。 ...

    android应用开发大全6

    在《Android应用开发大全6》中,我们深入探讨了Android平台上的应用程序开发,这是一个涵盖广泛且不断演进的领域。Android作为全球最流行的移动操作系统,为开发者提供了丰富的工具和技术来构建创新的应用。以下是对...

    基于Android的网上购物系统.zip

    "基于Android的网上购物系统"是一个针对移动设备开发的电子商务应用程序,它允许用户在Android平台上进行在线购物。这样的系统通常包括商品浏览、搜索、添加到购物车、下单、支付以及用户反馈等一系列功能,为用户...

    hybrid_example:适用于 iOS 和 Android 的混合应用程序示例

    "hybrid_example:适用于 iOS 和 Android 的混合应用程序示例"是一个很好的学习资源,旨在帮助开发者理解如何构建既能运行在iOS又能在Android平台上,并且利用JavaScript技术的混合应用。 **什么是混合应用程序?** ...

Global site tag (gtag.js) - Google Analytics