• Android应用开发 WebView与服务器端的Js交互


    复制代码
    最近公司再添加功能的时候,有一部分功能是用的html,在一个浏览器或webview中展示出html即可。当然在这里我们当然用webview控件喽
    
     
    
    WebApp的好处:
    
    在应用里嵌套web的好处有这么几点,1,跨平台,不仅可以在Android上运行,也可以在iOS上运行,而且样式什么的绝对统一,因为都是加载的html,用的都是同一套html
    
    2,修改灵活,容易更新版本。例如大家常看到的app里面的广告页,大多是嵌套的html,这样只要后台替换一下页面的内容,手机端就会改变展现内容,跟新版本也是如此,因为界面什么得成了在服务器端,所以要是想跟新界面什么得,只需要在后台修改在发布即可,不需要用户再重新下载app。这个好处我觉得对ios是有很大帮助的,哈哈,绕开苹果审核嘛,由于html我们可以随意替换,审核时可以把违规的部分隐藏,上线之后就可以随意改了,哈哈,你们懂得。
    
     
    
    当然,开发webapp当然也有局限,就是网速什么的,这个咱无法改变,这里也不废话。不过在开发中呢,如果只是页面之间的交互的话,我们只需提供一个webview控件即可,
    
    可是要是涉及到和手机设备或软件交互的话(如打开相册,摄像头等等),这就需要我们和页面经行js交互,js交互可以说是双向的,一种是,我们调用页面的,就是调用服务端的js方法,另一个呢则是服务端调用我们Android里面的代码,调用其实很简单,下面说一下怎样调用。
    
    当然我们先等有一个WebView,先创建一个Activity,然后设置布局,穿件WebView,布局和Activity如下:
    
    activity_webview.xml
    
    
    
    [html] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.<?xml version="1.0" encoding="utf-8"?>  
    02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    03.    android:layout_width="match_parent"  
    04.    android:layout_height="match_parent"  
    05.    android:orientation="vertical" >  
    06.    <WebView   
    07.        android:id="@+id/webview"  
    08.        android:layout_width="match_parent"  
    09.        android:layout_height="match_parent"  
    10.        />  
    11.  
    12.</LinearLayout>  
    
    
    
    
    然后是activity,
    
    WebViewActivity.activity
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.import android.app.Activity;  
    02.import android.os.Bundle;  
    03.import android.webkit.WebSettings;  
    04.import android.webkit.WebView;  
    05.  
    06.public class WebViewActivity extends Activity {  
    07.    private static final String url = "http://192.168.30.199:8080/song/test.html";  
    08.    private WebView mWebView;  
    09.    @Override  
    10.    protected void onCreate(Bundle savedInstanceState) {  
    11.        super.onCreate(savedInstanceState);  
    12.        setContentView(R.layout.activity_webviw);  
    13.        initView();  
    14.    }  
    15.  
    16.    private void initView() {  
    17.        mWebView = (WebView) findViewById(R.id.webview);  
    18.        //或的WebView的Setting  
    19.        WebSettings settings = mWebView.getSettings();  
    20.        //设置支持js,看方法名字就知道啥意思  
    21.        settings.setJavaScriptEnabled(true);  
    22.        //加载网页路径  
    23.        mWebView.loadUrl(url);  
    24.    }  
    25.}  
    
    
    
    
    上面就是一个简单的webview,然后很常规的设置属性,然后再加载要加载的页面路径,这样一般就可在网页里面自由点击跳转了,但是要和手机交互的话需要我们写js交互的代码了。
    
    首先说怎样调用服务器端的js方法,很简单,和加载网页路径基本上一样如下:
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.mWebView.loadUrl("javascript:forSmallPhoto()");  
    
    
    
    
    就这么简单的一句话你就可以调用服务器端的js方法了,其中JavaScript:是固定写法forSmallPhoto()则是服务端的js方法名字,这是一个无参数的方法,当然也可以传参,这需要我们拼凑字符串,mWebView.loadUrl("javascript:forSmallPhoto('" + data + "')");其中data就是一个变量,也就是你要传的参数值,当然也可以支持多参数传送,这得看你服务器端的js方法有几个参数了,其实就是我们调用一个方法一样,只不过这个方法是在服务器端的。我们调用服务器js,是为了,当Android完成某些功能后,需要告诉服务器,则我们可以调用js来告诉他我们完成了。
    
     
    
    在一种就是,服务端调用我们的Android代码了,这里Android中也是封装好了接口
    
    我们可以通过void android.webkit.WebView.addJavascriptInterface(Object object, String name)的方法来实现服务器端调用我们的代码,其中这个方法有两个参数,一个是object,另一个是String类型的; 只要webview调用了这个方法就可以调用我们的代码了。而要调用的代码我们写在Object里面,首先我们就先实现这个Object,我们创建一个类,JavaScriptInterface。Android中APi Guides中提供的Demo中取得累的名字是JavaScriptInterface,那我们也用这个名字把。然后实现它,然后随便在里面写一个方法,如下面
    
    JavaScriptInterface.Java类
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.import java.util.HashMap;  
    02.import java.util.Map;  
    03.  
    04.import android.content.Context;  
    05.import android.os.Handler;  
    06.import android.os.Message;  
    07.import android.text.TextUtils;  
    08.import android.util.Log;  
    09.import android.webkit.JavascriptInterface;  
    10.import android.widget.Toast;  
    11.  
    12./** 
    13. *  
    14. * Title: JavaScriptInterface.java Description: 
    15. *  
    16. * @author Liusong 
    17. * @version V1.0 
    18. */  
    19.public class JavaScriptInterface {    
    20.          
    21.    /** Instantiate the interface and set the context */  
    22.    public JavaScriptInterface() {  
    23.    }  
    24.  
    25.    /** Show a toast from the web page */  
    26.    @JavascriptInterface  
    27.    public void showToast() {  
    28.        Log.i("TAG", "调用成功==================》》》》》");  
    29.  
    30.    }  
    31.  
    32.}  
    
    
    
    
    
    这样就完成了一个简单的JavaScriptInterface类,这个类的方法是自己随便写的,其中,先说一下这里要注意的几点,首先重要的@JavascriptInterface这个注解,你会发现去掉也不会报错,但是这个是很早重要的,如果你想让服务器端调用你的方法,你就要加上这个注解@JavascriptInterface。在4.4api中说道,一定要加这个注解,负责调用不会成功,其实我在开发中,用红米1s,4.3的系统,就没法调用成功了,当时还纳闷,因为当时手里的文档是4.2的,很是郁闷。所以在这里强掉,一定要在自己写的方法前面加上@JavascriptInterface。
    
    还有一个注意的是方法的参数,这里是一个无参方法,当然这里你也可以写一个有参方法,这里先提一下,待会会配合html里面的js说道,我们先说void android.webkit.WebView.addJavascriptInterface(Object object, String name)这个方法里面的第二个参数,第二个参数你可以理解为是标识符,就是服务器端调用你方法时,需要找到你,怎么找到?就是通过这个标识符,标识符是自己随便定的,但是,你要告诉后台开发人员你的标识符是什么,我们这里把这第二个参数设置为“Android”。下面我给出我测试的html代码结合着看你就明白了。
    
    test.html
    
    
    
    [html] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.<!doctype html>  
    02.<html>  
    03.<head>  
    04.    <meta name="viewport" content="width=device-width, initial-scale=1" charset="GBK">  
    05.    <title>测试</title>  
    06.</head>  
    07.  
    08.<body>  
    09.  
    10.<div data-role="page" >  
    11.      
    12.<script type="text/javascript">  
    13.     function callAndroidAction(action) {  
    14.        Android.showToast();        alert("我敢保证,你现在用的是演示一");  
    15.    }  
    16.     function forSmallPhoto(action) {  
    17.        alert("我敢保证,你现在用的是演示一"+action);  
    18.    }  
    19.</script>  
    20.  
    21.    <div data-role="header">  
    22.        <h1>调用图库</h1>  
    23.        <!--   <a href="#" class="ui-btn">返回</a>-->  
    24.    </div>  
    25.  
    26.    <div data-role="main" class="ui-content">  
    27.  
    28.        <div style=" 98%;margin: 0 auto; text-align: center">  
    29.            <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction(0)">调用图库  </a>  
    30.              
    31.            <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction('2')"> 充值  </a>  
    32.          
    33.        </div>  
    34.  
    35.  
    36.    </div>  
    37.  
    38.     
    39.</div>  
    40.  
    41.</body>  
    42.  
    43.  
    44.</html>  
    
    
    
    
    
    这个代码有点乱,就将就这看吧,我是把这个页面放在自己的tomcat上的,其中这个html中大家发现
     
    
    
    
    [html] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.<script type="text/javascript">  
    02.    function callAndroidAction(action) {  
    03.        Android.showToast();  
    04.        alert("我敢保证,你现在用的是演示一");  
    05.    }  
    06.   function forSmallPhoto(action) {  
    07.        alert("我敢保证,你现在用的是演示一"+action);  
    08.    }  
    09.</script>  
    
    
    
    
    
      
    
    这个js方法没,看见里面的Android标识符没,没错,后台就是这么调用我们代码的,Android.showToast();就是这么调用的,就是这么简单,不要想的太难,我们就需按我上面说的那样,把Object实现,把标识符写好就ok了。饭后,后台就会通过标识符和你Object的方法名字调用你的方法。这里要说一下,你Object(即JavaScriptInterface,我们上面已经实现)里的方法的参数要和后台调用你的方法的参数个数和类型一直,就像我们平时调用方法是一样的。这一点知道了就好了。
    
    这样就可以了。
    
    所以WebViewActivity里面加上这一句就可以了。
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.view.addJavascriptInterface(new JavaScriptInterface(),"Android");  
    
    
    
    
     
    
    这样js就说完了。
    
    模版
    
    当后台要调用我们的代码,我们就写一个方法,如果调用多次我们就写多个,这样太麻烦,所以我们来写一个通用的方法,就是无论后台调用你代码干不同的事,都调用你这个方法,那怎么区分不同的执行动作呢?用传的参数,我们在JavaScriptInterface里面写一个方法,这里就叫callAndroidAction,我设计的是给这个方法三个参数,
    
    public void callAndroidAction(String action, String url,String json),第一个参数action,即用来表示要执行的动作,第二个则是url,不管是服务其给的下载路径还是,访问其他页面的路径,在一个json就是其他一些参数,由于传的参数不固定,我们就用一个参数,一个参数时就传过来,多个参数时可以通过json字符串传过来,就没必要麻烦一个一个的写参数了。
    
    然后我们在设计一个回调,让操作的代码拿出去,怎大体就是这样了
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.import java.util.HashMap;  
    02.import java.util.Map;  
    03.  
    04.import android.content.Context;  
    05.import android.os.Handler;  
    06.import android.os.Message;  
    07.import android.text.TextUtils;  
    08.import android.util.Log;  
    09.import android.webkit.JavascriptInterface;  
    10.import android.widget.Toast;  
    11.  
    12./** 
    13. *  
    14. * Title: JavaScriptInterface.java Description: 
    15. *  
    16. * @author Liusong 
    17. * @version V1.0 
    18. */  
    19.public class JavaScriptInterface {  
    20.      
    21.    private Handler mHandler;  
    22.      
    23.    /** Instantiate the interface and set the context */  
    24.    public JavaScriptInterface(Handler handler) {  
    25.        mHandler = handler;  
    26.    }  
    27.  
    28.    /** Show a toast from the web page */  
    29.    @JavascriptInterface  
    30.    public void showToast(final String toast) {  
    31.        Log.i("TAG", "调用成功==================》》》》》");  
    32.    }  
    33.  
    34.    @JavascriptInterface  
    35.    public void callAndroidAction(String action, String url,String json) {  
    36.        Map<String, String> params = new HashMap<String, String>();  
    37.        if(!TextUtils.isEmpty(url)){  
    38.            params.put("url", url);  
    39.        }  
    40.        if(!TextUtils.isEmpty(json)){  
    41.            params.put("json", json);  
    42.        }  
    43.        Message msg = Message.obtain();  
    44.        msg.what = Integer.valueOf(action);  
    45.        msg.obj = params;  
    46.        mHandler.sendMessage(msg);  
    47.    }  
    48.}  
    
    
    
    
    
    这样我们就从服务其拿到的参数都给Handler了,则WebViewActivity里面就要这样写了
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.import java.util.HashMap;  
    02.import java.util.Map;  
    03.  
    04.import android.app.Activity;  
    05.import android.os.Bundle;  
    06.import android.os.Handler;  
    07.import android.os.Message;  
    08.import android.webkit.WebSettings;  
    09.import android.webkit.WebView;  
    10.  
    11.public class WebViewActivity extends Activity {  
    12.    private static final String url = "http://192.168.30.199:8080/song/test.html";  
    13.      
    14.    //执行动作  
    15.    public static final int SELECT_IMAGE = 0;// 打开图库  
    16.    public static final int OPEN_PAGE = 1;// 跳转其他特定页面  
    17.    public static final int CLOSE_OR_BACK = 2;// 关闭或  
    18.      
    19.    private WebView mWebView;  
    20.    @Override  
    21.    protected void onCreate(Bundle savedInstanceState) {  
    22.        super.onCreate(savedInstanceState);  
    23.        setContentView(R.layout.activity_webviw);  
    24.        initView();  
    25.    }  
    26.   <p>  
    27.     private void getIntentDatas() {  
    28.          // TODO Auto-generated method stub  
    29.        url = getIntent().getStringExtra("url");  
    30.   }</p><p> </p>    private void initView() {  
    31.        mWebView = (WebView) findViewById(R.id.webview);  
    32.        //或的WebView的Setting  
    33.        WebSettings settings = mWebView.getSettings();  
    34.        //设置支持js,看方法名字就知道啥意思  
    35.        settings.setJavaScriptEnabled(true);  
    36.        mWebView.addJavascriptInterface(new JavaScriptInterface(handler), "Android");  
    37.        //加载网页路径  
    38.        mWebView.loadUrl(url);  
    39.    }  
    40.      
    41.    private Handler handler = new Handler(){  
    42.        public void handleMessage(Message msg) {  
    43.            switch (msg.what) {  
    44.            case SELECT_IMAGE://执行打开图库,  
    45.                  
    46.                //如果有参数,取服务端传过来的参数(url,json)  
    47.                Map<String, String> params = (HashMap<String, String>)msg.obj;  
    48.                break;  
    49.                  
    50.            //其他功能,可随着自己功能的增加,在这里增加,只需和后台商量好动作的action值即可  
    51.            default:  
    52.                break;  
    53.            }  
    54.        };  
    55.    };  
    56.}  
    
    
    
    
    最后再让WebViewActivity通用,就是通过传url参数
    
    
    
    [java] view plain copy print?在CODE上查看代码片派生到我的代码片
    01.private void getIntentDatas() {  
    02. // TODO Auto-generated method stub  
    03. url = getIntent().getStringExtra("url");  
    04.}  
    复制代码
  • 相关阅读:
    在一页纸上打印8页PPT讲义的方法
    如何用XML数据绑定前台Repeater
    ASP.net中导出Excel的简单方法
    鼠标浮上JS自动弹窗
    通过拖动百度地图的添加覆盖物获取所在地的经纬度坐标
    void FillSolidRect(lpRect,clr)无效原因现象。
    WM_DRAWITEM与DrawItem()的讨论
    自绘控件 CSatic无法响应OnDrawItem
    【原创】CListCtrl和CImageList显示缩略图,图片自动排列。
    【转】VC改变对话框按钮字体颜色和背景的解决方案
  • 原文地址:https://www.cnblogs.com/ldq2016/p/6769397.html
Copyright © 2020-2023  润新知