Android WebView与JS交互实例

与js交互示例.jpg

正文

一切基于项目WebViewStudy来说明,都是最小单元案例,可作为参考研究,本文从几个方面来讲解:

  • 1、Java调用WebView里的js代码(传递参数)
  • 2、WebView里的js代码调用Java本地方法(传递参数)
  • 3、外部注入js代码
  • 4、WebView长按事件

相关JS代码:

<html>
<head>
    <title>js调用android原生代码</title>
    <meta http-equiv="Content-Type" content="text/html;charset=gb2312">
    <meta id="viewport" name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui">
    <script type="text/javascript">
        function javacalljs(){
             document.getElementById("content").innerHTML +=
                 "<br\>java调用了js函数,无参";
        }

        <!--这里取到的是 android端传过来的数据-->
        function javacalljswithargs(data){
             document.getElementById("content").innerHTML +=
                 ("<br\>"+data);
        }

    </script>
</head>
<body>
    <br/><br/>
    <li><a onClick="window.injectedObject.startFunction()">点击调用java代码</a></li>
    <!--可以将android端传过来的数据,处理后,放在这里再传给android端-->
    <li><a onClick="window.injectedObject.startFunction('我是网页传出来的数据')">点击调用java代码并传递参数</a></li><br/>
<div id="content">内容显示</div>
</body>
</html>

Java调用WebView里的js代码(传递参数)

// 告诉WebView启用JavaScript执行。默认的是false。
ws.setJavaScriptEnabled(true);
1、如果点击调用就直接执行就好:

// 无参数调用
webView.loadUrl("javascript:javacalljs()");
// 传递参数调用
webView.loadUrl("javascript:javacalljswithargs('" + "android传入到网页里的数据,有参" + "')");

2、如果是显示后就调用,注意放在html显示完成之后
MyWebViewClient.java

@Override
    public void onPageFinished(WebView view, String url) {
        // 无参数调用
        webView.loadUrl("javascript:javacalljs()");
        // 传递参数调用
        webView.loadUrl("javascript:javacalljswithargs('" + "android传入到网页里的数据,有参" + "')");
        super.onPageFinished(view, url);
    }
    /**
     * 4.4以上可用 evaluateJavascript 效率高
     */
    private void load(String jsCode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            evaluateJavascript(jsCode, null);
        } else {
            loadUrl(jsCode);
        }
    }

WebView里的js代码调用Java本地方法(传递参数)

这里有一个js点击方法:

<li><a onClick="window.injectedObject.startFunction()">点击调用java代码</a></li>
<li><a onClick="window.injectedObject.startFunction('我是网页传出来的数据')">点击调用java代码并传递参数</a></li>

实现与js交互接口:

webView.addJavascriptInterface(new MyJavascriptInterface(this), "injectedObject");

这里的"injectedObject"对应js里的"window.injectedObject.startFunction()",其中MyJavascriptInterface.java:

/**
 * Created by jingbin on 2016/11/17.
 * js通信接口
 */
public class MyJavascriptInterface {
    private Context context;

    public MyJavascriptInterface(Context context) {
        this.context = context;
    }

    /**
     * 前端代码嵌入js:
     * imageClick 名应和js函数方法名一致
     *
     * @param src 图片的链接
     */
    @JavascriptInterface
    public void imageClick(String src) {
        Log.e("imageClick", "----点击了图片");
        Log.e("src", src);
    }

    /**
     * 前端代码嵌入js
     * 遍历<li>节点
     *
     * @param type    <li>节点下type属性的值
     * @param item_pk item_pk属性的值
     */
    @JavascriptInterface
    public void textClick(String type, String item_pk) {
        if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(item_pk)) {
            Log.e("textClick", "----点击了文字");
            Log.e("type", type);
            Log.e("item_pk", item_pk);
        }
    }

    /**
     * 网页使用的js,方法无参数
     */
    @JavascriptInterface
    public void startFunction() {
        Log.e("startFunction", "----无参");
    }

    /**
     * 网页使用的js,方法有参数,且参数名为data
     *
     * @param data 网页js里的参数名
     */
    @JavascriptInterface
    public void startFunction(String data) {
        Log.e("startFunction", "----有参" + data);
    }
}

且对标里面的两个方法:

    /**
     * 网页使用的js,方法无参数
     */
    @JavascriptInterface
    public void startFunction() {
        Log.e("startFunction", "----无参");
    }

    /**
     * 网页使用的js,方法有参数,且参数名为data
     *
     * @param data 网页js里的参数名
     */
    @JavascriptInterface
    public void startFunction(String data) {
        Log.e("startFunction", "----有参" + data);
    }

外部注入js代码

有时候我们得到一个网页,这个网页并不是我们订制的,里面没有我们调用的js代码,这时候我们可在前端直接注入js的。
比如 网页里面有图片,我们点击图片想要查看图片和保存图片到本地,这时候网页并没有实现这个js方法供我们调用,但是我们可以注入js代码,来实现这个需求。

在html加载完成之后,我们调用这段js:

// 这段js函数的功能就是,遍历所有的img节点,并添加onclick函数,函数的功能是在图片点击的时候调用本地java接口并传递url过去
webView.loadUrl("javascript:(function(){" +
        "var objs = document.getElementsByTagName(\"img\");" +
        "for(var i=0;i<objs.length;i++)" +
        "{" +
        "objs[i].onclick=function(){window.injectedObject.imageClick(this.getAttribute(\"src\"));}" +
        "}" +
        "})()");

这时候再看MyJavascriptInterface.java里的imageClick方法:

    /**
     * 前端代码嵌入js:
     * imageClick 名应和js函数方法名一致
     *
     * @param src 图片的链接
     */
    @JavascriptInterface
    public void imageClick(String src) {
        Log.e("imageClick", "----点击了图片");
        Log.e("src", src);
    }

src即为图片链接,可以作为显示和下载用。

WebView长按事件

webView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        final WebView.HitTestResult hitTestResult = webView.getHitTestResult();
        // 如果是图片类型或者是带有图片链接的类型
        if (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE ||
                hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
            // 弹出保存图片的对话框
            new AlertDialog.Builder(WebViewActivity.this)
                    .setItems(new String[]{"查看大图", "保存图片到相册"}, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            String picUrl = hitTestResult.getExtra();
                            //获取图片
                            Log.e("picUrl", picUrl);
                            switch (which) {
                                case 0:
                                    break;
                                case 1:
                                    break;
                                default:
                                    break;
                            }
                        }
                    })
                    .show();
            return true;
        }
        return false;
    }
});

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,050评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,538评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,673评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,622评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,047评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,974评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,129评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,893评论 0 209
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,654评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,828评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,297评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,619评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,326评论 3 243
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,176评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,975评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,118评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,909评论 2 278