WebView的使用以及Android与Js的交互

转载请注明原文链接:http://blog.csdn.net/u012975370/article/details/53006540


WebView的官方文档地址:https://developer.android.google.cn/reference/android/webkit/WebView.html

1.WebView基础使用

1.想要使用WebView,需要在<manifest>中添加权限:

<uses-permission android:name="android.permission.INTERNET" />
2.我们可以在xml文件中使用<WebView>控件,也可以在我们自己的activity中直接创建

 WebView webview = new WebView(this);
 setContentView(webview);
3.我们想要根据WebView来做一些自己的操作,一般通过两个事件来处理,分别是WebViewClient和WebChromeClient。

 WebChromeClient会在一些影响浏览器ui交互动作发生时被调用,比如WebView关闭和隐藏、页面加载进展、js确认框和警告框、js加载前、js操作超时、webView获得焦点等等

(1).WebChromeClient 会在一些影响浏览器ui交互动作发生时被调用,比如web关闭和隐藏,页面加载进展进度条的显示、js确认框和警告框、js加载前、js操作超时、webview获得焦点等等。相关方法查看文档(https://developer.android.com/reference/android/webkit/WebChromeClient.html

(2).WebViewClient可以提供页面加载各个阶段的回调,包括onPageStarted()和onPageFinished()等方法,也可以调用shouldOverrideUrlloading()来拦截url。这段代码还有一个作用,就是当需要从一个网页跳转到另一个网页时,我们希望目标网页仍然在当前WebView中,而不是打开系统浏览器。相关方法查看文档(https://developer.android.com/reference/android/webkit/WebViewClient.html

4.我们想要实现android和js的交互,必须获得一个WebSettings对象,调用setJavaScriptEnabled()方法,

webview.getSettings().setJavaScriptEnabled(true);

 注意:因为安全问题的考虑google在使用android API17以上的版本的时候,需要通过@JavascriptInterface来注解的Java函数才能被识别可以被js调用。

5.加载网页调用loadUrl(str)方法

 webview.loadUrl("http://developer.android.com/");

可以传入一个网络地址,也可以传入一个本地的html资源文件。

6.webview加载微信公众号连接,“阅读原文”无响应

由于dom内存没有启用,所以导致了js加载失败

getSettings().setDomStorageEnabled(true);

7.webview获得内容长度

//        getContentHeight 返回的是整个html 的高度,但并不等同于当前整个页面的高度,
//        因为WebView 有缩放功能, 所以当前整个页面的高度实际上应该是原始html 的高度再乘上缩放比例.
//        因此,更正后的结果,准确的判断方法应该是:
        mWebView.getContentHeight()*mWebView.getScale();

8.WebView缓存

当我们加载Htlm的时候,会在我们的data/包名/下生成database和cache两个文件夹。

我们请求的url记录会保存在webviewCache.db里,而url的内容则是保存在webviewcache文件夹下。

webview存在着两种缓存:网页数据缓存(存储打开过的页面及资源)、H5缓存(即AppCache)

1). 缓存模式的设置:

webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);  //设置 缓存模式  
总共有五种模式可选择:

LOAD_CACHE_ONLY  不使用网络,只读取本地缓存数据

LOAD_DEFAULT   根据cache-control来决定是否从网络上读取数据

LOAD_CACHE_NORMAL   API level 17中已经废弃,从API level 11 开始作用同LOAD_DEFAULT模式

LOAD_NO_CACHE   不使用缓存,只从网络获取数据

LOAD_CACHE_ELSE_NETWORK   只要本地有,无论是否过去,或者no-cache,都是用缓存中的数据

2). H5缓存

通过setAppCacheEnabled(boolean falg) 设置h5缓存是否打开,默认关闭。

通过setAppCachePath(String appCachePath) 提供的路径,在h5使用缓存过程中生成的缓存文件。

通过setAppCacheMaxSize(long appCacheMaxSize) 设置缓存最大容量。

		// 开始app缓存
		webview.getSettings().setAppCacheEnabled(true);
		// 设置缓冲大小 
		webview.getSettings().setAppCacheMaxSize(1024 * 1024 * 16);
		// 设置缓冲路径
		String appCacheDir = getApplicationContext().getDir("cache",
				Context.MODE_PRIVATE).getPath();
		webview.getSettings().setAppCachePath(appCacheDir);
3). 其他相关的设置

// 开启 DOM storage API 功能
webSettings.setDomStorageEnabled(true);
//开启 database storage API 功能
webSettings.setDatabaseEnabled(true);
//设置可以访问文件
webSettings.setAllowFileAccess(true);
//设置支持缩放
webSettings.setBuiltInZoomControls(true);

http://blog.sina.com.cn/s/blog_61cf99580102vj36.html

http://blog.csdn.net/t12x3456/article/details/13769731/#comments


2.Android调用Js

只需要在loadUrl里面的参数格式为“javascript:方法名()”,例如,html中有一个方法名叫做javaCallJs(),在android中调用这个方法的代码如下:

mWebView.loadUrl("javascript:javaCallJs()");
实现如下效果:


JavaCallJsActivity.java

package com.example.android_js;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Button;

/**
 * Created by jian on 2016/10/31.
 */
public class JavaCallJsActivity extends Activity {

    private Button btn1, btn2, btn3;
    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_javacalljs1);

        initView();

        // 设置webview的javascript可用
        mWebView.getSettings().setJavaScriptEnabled(true);
        // 加载html,可网络,可本地
        mWebView.loadUrl("file:///android_asset/JavaCallJs.html");
        // 不加下面这句话,是无法调起alert的
        mWebView.setWebChromeClient(new WebChromeClient());
    }

    private void initView() {
        btn1 = (Button) findViewById(R.id.java_call_js1_btn1);
        btn2 = (Button) findViewById(R.id.java_call_js1_btn2);
        btn3 = (Button) findViewById(R.id.java_call_js1_btn3);
        mWebView = (WebView) findViewById(R.id.java_call_js1_webview);

        btn1.setOnClickListener(mOnClickListener);
        btn2.setOnClickListener(mOnClickListener);
        btn3.setOnClickListener(mOnClickListener);
    }

    View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.java_call_js1_btn1:
                    mWebView.loadUrl("javascript:javaCallJsNoArgs()");
                    break;
                case R.id.java_call_js1_btn2:
                    mWebView.loadUrl("javascript:javaCallJsExistArgs('我是聂建')");
                    break;
                case R.id.java_call_js1_btn3:
                    mWebView.loadUrl("javascript:showAlert('出现了alert!')");
                    break;
            }
        }
    };

}
activity_javacalljs1.xml

<?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"
              android:padding="10dp">

    <Button
        android:id="@+id/java_call_js1_btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="java调用js无参方法"/>

    <Button
        android:id="@+id/java_call_js1_btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="java调用js有参方法"/>

    <Button
        android:id="@+id/java_call_js1_btn3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="java调用js的dialog"/>

    <WebView
        android:id="@+id/java_call_js1_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
JavaCallJs.html

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>Java调用JavaScript</title>
		<style>
			#javacalljs1,
			#javacalljs2 {
				color: red;
			}
		</style>
		<script type="text/javascript">
			function javaCallJsNoArgs() {
				document.getElementById("javacalljs1").innerHTML += "Java调用了我的无参函数<br\>";
			}

			function javaCallJsExistArgs(args) {
				document.getElementById("javacalljs2").innerHTML += "Java调用了我的有参函数,参数是:" + args + "<br\>";
			}

			function showAlert(args) {
				alert(args);
			}
		</script>
	</head>

	<body>
		这是NieJian写的Java调用Js的验证页面!<br /><br /> 点击按钮:“java调用js无参方法”。会出现以下内容:
		<br />
		<div id="javacalljs1"></div><br /><br /> 点击按钮:“java调用js有参方法”。会出现以下内容:
		<br />
		<div id="javacalljs2"></div>
	</body>

</html>

3.Js调用Android

Js调用Android,首先要在android代码中注册一个对象,调用如下方法:

void addJavascriptInterface (Object object,String name)

Object: the Java object to inject into this WebView's JavaScript context. Null values are ignored.
String: the name used to expose the object in JavaScript
这个方法是将object这个java对象注入到webview中,然后在webview中通过name这个字段来唯一标识调用object这个java对象中的方法。

 For applications targeted to API level JELLY_BEAN_MR1 and above, only public methods that are annotated with 
JavascriptInterface can be accessed from JavaScript. For applications targeted to API level JELLY_BEAN or below, 
all public methods (including the inherited ones) can be accessed
根据文档介绍,API17开始,就必须添加 @JavascriptInterface 注解,,而且方法必须是public修饰,否则,不生效,API16及以下的public方法可以不添加注解。

class JsObject {
    @JavascriptInterface
    public String toString() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new JsObject(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");
下面是一个小案例,实现效果如下:

JsCallJavaActivity.java

package com.example.android_js;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;

/**
 * Created by jian on 2016/10/31.
 */
public class JsCallJavaActivity extends Activity {

    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_javacalljs2);

        initWebView();
    }

    private void initWebView() {
        mWebView = (WebView) findViewById(R.id.java_call_js2_webview);
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDefaultTextEncodingName("utf-8");

        // 添加一个对象,让js对象可以访问该对象的方法
        mWebView.addJavascriptInterface(new MyObject(), "niejian_android");
        mWebView.loadUrl("file:///android_asset/JsCallJava.html");
    }

    class MyObject {
        /**
         * API 17必须添加 @JavascriptInterface注解,否则会导致反射失败,调用无效
         */
        @JavascriptInterface
        public void javaCallJsMethod1() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mWebView.loadUrl("javascript:javaCallJsNoArgs()");
                }
            });
        }

        @JavascriptInterface
        public void javaCallJsMethod2() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mWebView.loadUrl("javascript:javaCallJsExistArgs('我是聂建')");
                }
            });
        }
    }
}
JsCallJava.html

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>JavaScript调用Java</title>
		<style>
			#content1,
			#content2 {
				color: red;
			}
		</style>
		<script type="text/javascript">
			function javaCallJsNoArgs() {
				document.getElementById("content1").innerHTML = "js调用java,Java再回调js的无参方法"
			}

			function javaCallJsExistArgs(args) {
				document.getElementById("content2").innerHTML = "js调用java,Java再回调js的无参方法,参数是:" + args;
			}
		</script>
	</head>

	<body>
		这是NieJian写的Java调用Js的验证页面2!<br />
		<input type="button" value="JS->Java->JS “无参方法”,请点击,查看下方" οnclick="window.niejian_android.javaCallJsMethod1()" /><br />
		<div id="content1"></div>
		<br /><br />
		<input type="button" value="JS->Java->JS “有参方法”,请点击,查看下方" οnclick="window.niejian_android.javaCallJsMethod2()" /><br />
		<div id="content2"></div>
	</body>

</html>



源码下载

https://github.com/NieJianJian/NieJ_CodeBase/tree/master/Android_Js


参考链接:https://juejin.im/entry/5914770f128fe1005ca599ce


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值