Android WebView 与JS的数据交互

我会带着你远行 2022-06-18 01:08 302阅读 0赞

原文 http://blog.csdn.net/cappuccinolau/article/details/8262821/

关于WebView

我们知道目前android市场上的一些应用采用的开发方式大致分为三种:Native App、Web App、Hybrid App。本文主要是Hybrid App中实现的主要技术native组件与js的数据交互的理解以及实现。

Android API中提供了WebView组件来实现对html的渲染。所谓的HybridApp开发方式即是汇集了HTML5、CSS3、jS的相关开发技术,以及数据交换格式json/XML。这显然是Web开发工程师的技能。正是因为如此,众多中小企业选择了这种开发方式来减少对android开发工程师的过度依赖,至于这三种开发方式的比较与优劣不在本文考虑之列。

有了WebView这个组件,Android应用开发技术也就转嫁到html与java数据交互上来。说白了就是js与WebView的数据交互,这就是本文所要讨论的。

#

WebView与js的数据交互

  1. WebView中载入静态页面

将WebView添加到应用中。和原生控件一样,在layout引入WebView控件。代码片段如下:

[html] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. <?**xml version=”1.0” encoding=”utf-8”?>**
  2. <**LinearLayout** xmlns:android=”http://schemas.android.com/apk/res/android“
  3. android:id=”@+id/linearLayout”
  4. android:layout_width=”match_parent”
  5. android:layout_height=”match_parent”
  6. android:background=”#000”
  7. android:orientation=”horizontal” >
  8. <**WebView**
  9. android:id=”@+id/webview”
  10. android:layout_width=”match_parent”
  11. android:layout_height=”match_parent”
  12. />
  13. </**LinearLayout**>

载入页面:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. webView = (WebView) findViewById(R.id.webview);
  2. webView.loadUrl(“file:///file:///android_asset/page.html”);

page.html存储在工程文件的assets根目录下。

  1. 引入jquery mobile

引入js框架让我们编写的html页面更接近于原生控件的显示效果。目前主流的移动应用js框架有:jquery mobile和sencha touch(jquery mobile与sencha touch的选型不在本文讨论范围)。本文选择使用jquery mobile。

首先,在webview添加对js的支持:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. WebSettings setting = webView.getSettings();
  2. setting.setJavaScriptEnabled(true);//支持js

增加对中文的支持:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. WebSettings setting = webView.getSettings();
  2. setting.setDefaultTextEncodingName(“GBK”);//设置字符编码

设置页面滚动条风格:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. webView.setScrollBarStyle(0);//滚动条风格,为0指滚动条不占用空间,直接覆盖在网页上

jquery mobile提供的标准页面模板TemplateForJQuery.html:

[html] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. <!DOCTYPE html>
  2. <**html**>
  3. <**head**>
  4. <**title**>Page Title</**title**>
  5. <**meta name=”viewport” content=”width=device-width, initial-scale=1”>**
  6. <**link rel=”stylesheet” href=”css/jquery.mobile-1.1.1.min.css” />**
  7. <**script src=”js/jquery.js”></script**>
  8. <**script src=”js/jquery.mobile-1.1.1.min.js”></script**>
  9. </**head**>
  10. <**body**>
  11. <**div data-role=”page”>**
  12. <**div data-role=”header”>**
  13. <**h1**>Page Title</**h1**>
  14. </**div**>
  15. <**div data-role=”content”>**
  16. <**p**>Page content goes here.</**p**>
  17. </**div**>
  18. <**div data-role=”footer”>**
  19. <**h4**>Page Footer</**h4**>
  20. </**div**>
  21. </**div**>
  22. </**body**>
  23. </**html**>

页面依赖的js库、css等均放在assets目录下,目录组织结构如下:

1354718697_2736.png

运行应用后的截图:

1354718779_7885.png

下面是button 的截图,与原生控件没什么明显区别,有种以假乱真的感觉:

1354718847_2149.png

  1. 良好的用户体验

运行我们的应用发现,在拥有大量js的页面被载入时,一直处于等待中,这是很糟糕的用户体验。可以加入进度条解决。注意到webview提供的两个方法:setWebViewClient和setWebChromeClient。其中setWebChromeClient方法正是可以处理progress的加载,此外,还可以处理js对话框,在webview中显示icon图标等。对于处理progress的代码片段如下:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. webView.setWebChromeClient(new WebChromeClient() {
  2. public void onProgressChanged(WebView view, int progress) { // 载入进度改变而触发
  3. if (progress == 100) {
  4. handler.sendEmptyMessage(1);// 如果全部载入,隐藏进度对话框
  5. }
  6. super.onProgressChanged(view, progress);
  7. }
  8. });

其中通过handler 消息机制来处理UI线程的更新:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. handler = new Handler() {
  2. public void handleMessage(Message msg) { // 定义一个Handler,用于处理下载线程与UI间通讯
  3. if (!Thread.currentThread().isInterrupted()){
  4. switch (msg.what) {
  5. case 0:
  6. pd.show();// 显示进度对话框
  7. break;
  8. case 1:
  9. pd.hide();// 隐藏进度对话框,不可使用dismiss()、cancel(),否则再次调用show()时,显示的对话框小圆圈不会动。
  10. break;
  11. }
  12. }
  13. super.handleMessage(msg);
  14. }
  15. };

对于setWebViewClient方法,一般用来处理html的加载(需要重载onPageStarted(WebView view, String url, Bitmap favicon))、关闭(需要重载onPageFinished(WebViewview, String url)方法)。

setWebViewClient和setWebChromeClient的作用:前者主要用于处理webView的控制问题,如加载、关闭、错误处理等;后者主要处理js对话框、图标、页面标题等。

  1. 获取java中的数据

单独构建一个接口,作为处理js与java的数据交互的桥梁,本文封装的代码AndroidToastForJs.java如下:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. public class AndroidToastForJs {
  2. private Context mContext;
  3. public AndroidToastForJs(Context context){
  4. this.mContext = context;
  5. }
  6. //webview中调用toast原生组件
  7. public void showToast(String toast) {
  8. Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
  9. }
  10. //webview中求和
  11. public int sum(int a,int b){
  12. return a+b;
  13. }
  14. //以json实现webview与js之间的数据交互
  15. public String jsontohtml(){
  16. JSONObject map;
  17. JSONArray array = new JSONArray();
  18. try {
  19. map = new JSONObject();
  20. map.put(“name”,”aaron”);
  21. map.put(“age”, 25);
  22. map.put(“address”, “中国上海”);
  23. array.put(map);
  24. map = new JSONObject();
  25. map.put(“name”,”jacky”);
  26. map.put(“age”, 22);
  27. map.put(“address”, “中国北京”);
  28. array.put(map);
  29. map = new JSONObject();
  30. map.put(“name”,”vans”);
  31. map.put(“age”, 26);
  32. map.put(“address”, “中国深圳”);
  33. map.put(“phone”,”13888888888”);
  34. array.put(map);
  35. } catch (JSONException e) {
  36. e.printStackTrace();
  37. }
  38. return array.toString();
  39. }
  40. }

Webview提供的传入js的方法:

[java] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. webView.addJavascriptInterface(new AndroidToastForJs(mContext), “JavaScriptInterface”);

Html页面jsonData.html设计的部分代码如下:

[html] view plain copy

在CODE上查看代码片 派生到我的代码片

  1. <**script type=”text/javascript”>**
  2. var result = JavaScriptInterface.jsontohtml();
  3. var obj = eval(“(“+result+”)”);//解析json字符串
  4. function showAndroidToast(toast)
  5. {
  6. JavaScriptInterface.showToast(toast);
  7. }
  8. function getjsonData(){
  9. var result = JavaScriptInterface.jsontohtml();
  10. var obj = eval(“(“+result+”)”);//解析json字符串
  11. for(i=0;i<**obj.length**;i++){
  12. var user=obj[i];
  13. document.write(“<**p**>姓名:”+user.name+”</**p**>“);
  14. document.write(“<**p**>年龄:”+user.age+”</**p**>“);
  15. document.write(“<**p**>地址:”+user.address+”</**p**>“);
  16. if(user.phone!=null){
  17. document.write(“<**p**>手机号码:”+user.address+”</**p**>“);
  18. }
  19. }
  20. }
  21. function list(){
  22. document.write(“<**div data-role=’header’><p**>another</**p></div>**”);
  23. }
  24. </**script**>
  25. </**head**>
  26. <**body**>
  27. <**div data-role=”page” >**
  28. <**div data-role=”header” data-theme=”c”>**
  29. <**h1**>Android via Interface</**h1**>
  30. </**div**>
  31. <**div data-role=”content”>**
  32. <**button value=”say hello” onclick=”showAndroidToast(‘Hello,Android!’)” data-theme=”e”></button**>
  33. <**button value=”get json data” onclick=”getjsonData()” data-theme=”e”></button**>
  34. </**div**>
  35. <**div data-role=”collapsible” data-theme=”c” data-content-theme=”f”>**
  36. <**h3**>I’m <**script**>document.write(obj[0].name);</**script**>,click to see my info</**h3**>
  37. <**p><script>document.write(“<p>姓名:”+obj[0].name+”</p>“);</script></p**>
  38. <**p><script>document.write(“<p>年龄:”+obj[0].age+”</p>“);</script></p**>
  39. <**p><script>document.write(“<p>地址:”+obj[0].address+”</p>“);</script></p**>
  40. </**div**>
  41. <**div data-role=”footer” data-theme=”c”>**
  42. <**h4**>Page Footer</**h4**>
  43. </**div**>
  44. </**div**>
  45. </**body**>

点击say hello按钮运行的截图如下:

1354719179_9146.png1354719230_8207.png

发表评论

表情:
评论列表 (有 0 条评论,302人围观)

还没有评论,来说两句吧...

相关阅读

    相关 WebViewJS交互

    阅读:[JSBridge][] 前言:以下是webView和JS互相调用的基础介绍。 利用WebView调用网页上的JavaScript代码(java调用JS) 说白