android与H5交互

1 — WebView基本配置

2 —WebView和H5的交互

3 — WebView错误页面处理

4 —WebView中的Cookie操作

5 —WebView漏洞

6 —WebView内存泄漏问题

1WebView基本配置

布局设置


代码设置

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="50dp">

        <Button

            android:layout_width="0dp"

            android:layout_weight="1"

            android:layout_height="match_parent"

            android:id="@+id/btn1"

            android:text="无参调用"/>

        <Button

            android:layout_width="0dp"

            android:layout_weight="1"

            android:layout_height="match_parent"

            android:text="有参调用"

            android:id="@+id/btn2"/>

    </LinearLayout>

    <WebView

        android:id="@+id/wv"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:layout_weight="9" />

</LinearLayout>

初如化控件

        //初始化控件

        Button btn1 = (Button) findViewById(R.id.btn1);

        btn1.setOnClickListener(this);

        Button btn2 = (Button) findViewById(R.id.btn2);

        btn2.setOnClickListener(this);

        wv = (WebView) findViewById(R.id.wv);

        //获取webSettings

        WebSettings settings = wv.getSettings();

        //让webView支持JS

        settings.setJavaScriptEnabled(true);

        //加载百度网页

        wv.loadUrl("http://www.baidu.com/");

        //这个时候就能显示百度页面了


2 WebView和H5的交互

我们自己写一个H5页面 放在assets目录下

注意 : 如果html文件存于assets:则加前缀:file:///android_asset/

如果在Sdcard直接使用file:///sdcard/ or file:/sdcard也可以

  //加载本地assets目录下的静态网页

    wv.loadUrl("file:///android_asset/123.html");

    //第一个参数把自身传给js 第二个参数是this的一个名字

    //这个方法用于让H5调用android方法

    wv.addJavascriptInterface(this, "android");


Android调用JS方法

//这个是button的点击事件

@Override

    public void onClick(View v) {

        switch (v.getId()) {

            case R.id.btn1:

                //参数 “javascript:”  +  js方法名

                wv.loadUrl("javascript:message()");

                break;

            case R.id.btn2:

                //在android调用js有参的函数的时候参数要加单引号

                wv.loadUrl("javascript:message2('" + name + "')");

                break;

        }

    }

JS调用Android方法

    //下面的两个方法是让网页来调的

    //这个注解必须加 因为 兼容问题

    @JavascriptInterface

    public void setMessage() {

        Toast.makeText(this, "我弹", Toast.LENGTH_SHORT).show();

    }

    @JavascriptInterface

    public void setMessage(String name) {

        Toast.makeText(this, "我弹弹" + name, Toast.LENGTH_SHORT).show();

    }


H5代码,如果H5看不懂请自行百度

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <title></title>

</head>

<body>

<button id="btn0">调用android无参参数</button>

<button id="btn1">调用android有参参数</button>

<a href='aa://atguigu/path'>点我试试</a>

<a href='https://www.baidu.com'>百度</a>

<div id="content"></div>

</body>

<script type="text/javascript">

        var name = "啊福老师 哇哇哇"

        document.getElementById("btn0").onclick = function(){

        //android是传过来的对象名称,setmessage是android中的方法

            android.setMessage();

        };

        document.getElementById("btn1").onclick = function(){

        //android是传过来的对象名称,setmessage是android中的方法

                android.setMessage(name);

        };

        var content = document.getElementById("content");

        function message(){

            content.innerHTML = "调用了有参的js函数"

        };

        function message2(des){

            content.innerHTML = "调用了"+des;

        };

    </script>

</html>


第二种交互方式 而是采用scheme + cookie的方式

--1、Java 调用 js里面的函数、效率低、估计要200ms左右

而js去调Java的方法、速度很快、50ms左右、所以尽量用js调用Java方法

--2、Java 调用 js 的函数、没有返回值、调用了就控制不到了

--3、Js 调用 Java 的方法、返回值如果是字符串、你会发现这个字符串是 native 的、转成 locale 的才能正常使用

--4、网页中尽量不要使用jQuery、执行起来需要5-6秒、最好使用原生的js写业务脚本、以提升加载速度、改善用户体验

--5、Android4.2以下的系统存在着webview的js对象注入漏洞…Android API 16 没有正确限制使用webview.addJavaScripteInterface方法,远程攻击者 使用JavaReflectionAPI利用执行任意java对象的方法


scheme设置:对于要启动的Activity

//这一章不详细讲解scheme的使用

<activity android:name=".SecondActivity">

            <intent-filter>

                <data android:scheme="aa"/>

                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.DEFAULT"/>

                <category android:name="android.intent.category.BROWSABLE"/>

            </intent-filter>

        </activity>

看一下原来的H5代码

<a href='aa://atguigu/path'>点我试试</a>

注意:

//Url地址  aa://atguigu/path

下面的是Activity清单文件的配置

<data android:scheme="aa" android:host="atguigu" android:path="/path"/>

上下对比其实和我们的URL地址是一样的

aa 是 scheme

host 是主机名称

path 是路径

当然还可以配置端口和加参数

aa://atguigu:8080/path?id = 10

通过activity配置那么就可以跳转到相应的界面里,如果activity只配置scheme = aa那么只要是aa的Url都是适配的

wv.setWebViewClient(new WebViewClient() {

//当页面开始加载的时候调用此方法

            @Override

            public void onPageStarted(WebView view, String url, Bitmap favicon) {

                super.onPageStarted(view, url, favicon);

              //通过对URl的解析来决定调转到哪个页面

              //这边只是简单做一些判断当前是否是Scheme跳转

                if (url.contains("aa")) {

                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

                    startActivity(intent);

                }

            }

3WebView错误页面处理

场景 : 加载webview错误时加载网页的错误页面,体验不好,速度慢,这个时候就需要我们自行处理错误页面

第一步 先做一个错误的H5页面放在本地,或者加载Activity都可以

wv.setWebViewClient(new WebViewClient() {

    @Override

            public void onReceivedError(WebView view, int errorCode,

                                        String description, String failingUrl) {

                super.onReceivedError(view, errorCode, description, failingUrl);

                Log.i(TAG, "onReceivedError: " + errorCode + "  " + description);

                //判断错误类型

                if (errorCode == ERROR_UNSUPPORTED_SCHEME) {

                    Log.i(TAG, "onReceivedError: " + "true");

                    //停止加载错误页面,否则会显示原来H5加载的错误页面

                    //再跳到现在的错误页面,体验不好,当然也可以做其它操作

                    view.stopLoading();

                    view.loadUrl("file:///android_asset/error.html");

                }

            }

}


4WebView中的Cookie操作

关于Cookie的介绍在这不再详说

场景:webView需要保存从网页中获取到的Cookie 在涉及到账户体系的产品中,包含了一种登录状态的传递。比如,在Native(原生)界面的登录操作,进入到Web界面时,涉及到账户信息时,需要将登录状态传递到Web里面,避免用户二次登录。这里就涉及到WebView加载网页时的Cookie操作了。

通常我们在登录时获取到用户的Cookie信息,然后将其保存到sdcard的WebView缓存文件当中,这样在加载网页时,WebView会自动将当前url的本地Cookie信息放在http请求的request中,传递给服务器

获取cookie

//加载百度网站

wv.loadUrl("http://www.baidu.com");

wv.setWebViewClient(new WebViewClient() {

    @Override

            public void onPageStarted(WebView view, String url, Bitmap favicon) {

                super.onPageStarted(view, url, favicon);

              CookieManager instance = CookieManager.getInstance();

              //这样就可以获取到Cookie了

              String cookie = instance.getCookie(url);

              Log.i(TAG, "onPageStarted: "+cookie);

            }

}

设置cookie

        //创建CookieSyncManager 参数是上下文

        CookieSyncManager.createInstance(context);

        //得到CookieManager

        CookieManager cookieManager = CookieManager.getInstance();

        //得到向URL中添加的Cookie的值

        String cookieString;//获取方法不再详述,以项目要求而定

        //使用cookieManager..setCookie()向URL中添加Cookie

        cookieManager.setCookie(url, cookieString);

        CookieSyncManager.getInstance().sync();


5WebView漏洞和内存泄漏

/**

* ① Android API 16 没有正确限制使用webview.addJavaScripteInterface方法,远程攻击者使用 JavaReflectionAPI利用执行任意java对象的方法

*

* ② webview在布局文件中的使用:webView写在其它容器中时 (先销毁webview再销毁activity)因为 webview是独立进程,最好创建个viewGroup用来放置webview,Activity创建时add进来,在Activity停止时remove掉

*

* ③使用 jsbridge(详情看下面)

*

* ④ 在此方法的操作放到后者使用webviewClient.onPageFinished->WebChromeClient.onProgressChanged

*

* ⑤ 后台耗电问题 :activity不可见时要停用webview

*

* ⑥ webview硬件加速导致页面渲染问题-白屏展示(关闭硬件加速)

*

* ⑦动态添加webview,对传入webview中使用的context使用弱引用,动态添加webview意思在布局

* */

JSBridge

什么是JsBridge

WebViewJavascriptBridge是移动UIView和Html交互通信的桥梁,就是实现java和js的互相调用的桥梁。替代了WebView的自带的JavascriptInterface的接口,使得开发者更方便的让js和native灵活交互,使我们的开发更加灵活和安全。

1

JSBridge的优点

    Android API 4.4以前,谷歌的webview存在安全漏洞,网站可以通过js注入就可以随便拿到客户端的重要信息,甚至轻而易举的调用本地代码进行流氓行为,谷歌后来发现有此漏洞后,在API 4.4以后增加了防御措施,如果用js调用本地代码,开发者必须在代码申明JavascriptInterface, 列如在4.0之前我们要使得webView加载js只需如下代码:

mWebView.addJavascriptInterface(new JsToJava(), "myjsfunction");

4.4之后使用时需要在调用Java方法加入@JavascriptInterface注解,如果代码无此申明,那么也就无法使得js生效,也就是说这样就可以避免恶意网页利用js对客户端的进行窃取和攻击。 但是即使这样,我们很多时候需要在js调用本地java代码的时候,要做一些判断和限制,或者有的场景也会做些过滤或者对用户友好提示,甚至更复杂的Hybrid模式下,需要js和native之间进行交互通讯,拍照上传,因此原生的JavascriptInterface 就比较维护了,特此有了基于JavascriptInterface 封装的WebViewJavascriptBridge框架。

---------------------

作者:小龙哥的开发日记

来源:CSDN

原文:https://blog.csdn.net/w15321970103/article/details/75635454

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

推荐阅读更多精彩内容