Android WebView在API17后addJavascriptInterface方法无效


Webview是Android平台中一个重要组件,通常是通过在Activity中嵌套一个简单浏览器,实现在线网页浏览的功能或者实现Android与JavaScript的通信,此时addJavascriptInterface方法就显得尤为重要。但熟悉的人应该会有所发现,在API 17以后,addJavascriptInterface方法就失效了,下面将详细的介绍addJavascriptInterface方法以及失效解决方法。


一、 addJavascriptInterface简介

addJavascriptInterface是WebKit的原生API,属于WebView对象的公共方法,用于暴露一个java对象给js,使得js可以直接调用方法。当然,java与js的相互调用也离不开loadUrl()方法的配合使用。但是addJavascriptInterface的使用也是有些问题,因为Android平台封装WebKit内核时,不同的版本中会有些不一致。


二、网页内容

1. HTML代码

<html>
<head>
<meta charset="gb-2312">
<title>无标题文档</title>
<link href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" rel="stylesheet" type="text/css">
<script src="http://code.jquery.com/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js" type="text/javascript"></script>
</head>

<body>
<div data-role="page" id="page">
  <div data-role="header">
    <h1>标题</h1>
  </div>
  <div data-role="content">
    <ul data-role="listview" data-inset="true">
        <li data-role="list-divider">
        注册
        </li>
        <li>
          <div data-role="fieldcontain">
            <label for="username">用户名:</label>
            <input type="text" name="textinput" id="username" value="张三"  />
          </div></li><li>
          <div data-role="fieldcontain">
            <label for="password">密码:</label>
            <input type="password" name="textinput" id="password" value="zhangsan"  />
          </div></li><li>
          <div data-role="fieldcontain">
            <fieldset data-role="controlgroup" data-type="horizontal">
              <legend>性别:</legend>
              <input type="radio" name="radio1" id="man" value="0" />
              <label for="man">男</label>
              <input type="radio" name="radio1" id="woman" value="1" />
              <label for="woman">女</label>
            </fieldset>
          </div></li><li>
          <div data-role="fieldcontain">
            <fieldset data-role="controlgroup" data-type="horizontal">
              <legend>爱好</legend>
              <input type="checkbox" name="checkbox1" id="football" class="custom" value="0" />
              <label for="football">足球</label>
              <input type="checkbox" name="checkbox1" id="basketball" class="custom" value="1" />
              <label for="basketball">篮球</label>
              <input type="checkbox" name="checkbox1" id="vollyball" class="custom" value="2" />
              <label for="vollyball">排球</label>
            </fieldset>
          </div>
       </li>
       <li>
         <div data-role="fieldcontain">
           <label for="selectmenu" class="select">国籍:</label>
           <select name="selectmenu" id="selectmenu">
             <option value="China">中国</option>
             <option value="America">美国</option>
             <option value="Japan">日本</option>
           </select>
         </div>

       </li>
       <li>
         <button id="commit">提交</button>

        </li>
    </ul>
  </div>
  <div data-role="footer" data-position="fixed">
    <h4>脚注</h4>
  </div>
</div>
</body>
</html>

2.JS代码

<script>
    $(function(){
        $("#commit").click(function(){
            var result = "{";
            result +="\"username\":\"";
            result +=$("#username").val();

            result +="\",\"password\":\"";
            result +=$("#password").val();

            result += "\",\"gender\":\"";
            result += $('input[name="radio1"]:checked').val();

            result += "\",\"interest\":\"";
            $('input[name="checkbox1"]:checked').each(function() {
                result += $(this).val()+",";
            });

            result += "\",\"country\":\"";
            result += $("#selectmenu option:selected").text()+"\"}";
            register_js.register(result);
            });

        });
</script>

3.实现效果图

 


三、API 17以前addJavascriptInterface的使用方法

1.获取网页

wv = (WebView) this.findViewById(R.id.wv1);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.loadUrl("file:///android_asset/index.html");
        wv.addJavascriptInterface(new JSInterface(), "register_js")

register_js为交互时相互定义的名字。

2.JS中调用方法在Android中响应

public void register(String userInfo){
            Toast.makeText(MainActivity.this, userInfo, Toast.LENGTH_LONG).show();
        }
register方法为js中调用的方法名,与addJavascriptInterface相对应。具体可参照JavaScript的代码。


四、API 17以后addJavascriptInterface的使用方法

1. 获取网页

wv = (WebView) this.findViewById(R.id.wv1);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.loadUrl("file:///android_asset/index.html");
        wv.addJavascriptInterface(new JSInterface(), "register_js")

2.JS中调用方法在Android中响应

public void register(String userInfo){
            Toast.makeText(MainActivity.this, userInfo, Toast.LENGTH_LONG).show();
        }

3.注意

需要添加注解,否则addJavascriptInterface方法会失效。

@SuppressLint("JavascriptInterface")
@JavascriptInterface

4.方法更换原因

Android4.2以前WebView 提供了javascript 调用Java代码的方法,会造成很大的安全漏洞。Android官方在API 17后,限制javascript代码只能调用声明了@JavascriptInterface 注解的Java方法。

所以必须要给每个可供js代码调用的Java方法加一个@JavascriptInterface接口。

 

五、MainActivity.java代码

package com.example.administrator.addjavascriptinterfacefunctiontest;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private WebView wv;
    @SuppressLint("JavascriptInterface")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        wv = (WebView) this.findViewById(R.id.wv1);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.loadUrl("file:///android_asset/index.html");
        wv.addJavascriptInterface(new JSInterface(), "register_js");
    }

    private final class JSInterface{
        @SuppressLint("JavascriptInterface")
        @JavascriptInterface
        public void register(String userInfo){
            Toast.makeText(MainActivity.this, userInfo, Toast.LENGTH_LONG).show();
        }
    }
}

六、源码下载

地址:http://download.csdn.net/download/u012721519/10225784



Good luck!

Write by Jimmy.li

















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值