Android中的WebView组件本身就是一个浏览器实现。Android 5.0增强的WebView基于Chromium M37,直接支持WebTRC、WebAudio和WebGL。Chromium M37也包括对Web组件规范的原生支持,如自定义元素、阴影DOM、HTML导入和模板,这意味这开发者可以直接在WebView中使用Polymer和Material设计。

Android系统自带的浏览器其实也是基于开源的WebKit引擎实现的。

一. WebView的常用方法如下:

方法 描述
void goBack() 后退。
void goForward() 前进。
void loadUrl(String url) 加载指定URL对应的网页。
void loadUrl(String url, Map additionalHttpHeaders) 用额外的HTTP头加载指定的URL对应的网页。
boolean zoomIn() 放大网页。
boolean zoomOut() 缩小网页。
void addJavascriptInterface(Object object, String name) 将Java对象置入WebView中。
void clearCache(boolean includeDiskFiles) 清空缓存。
void clearHistory() 清空访问历史。
Bitmap getFavicon() 获取当前网页的favicon图标。
String getOriginalUrl() 获得当前网页的URL。
String getUrl() 获得当前网页的URL。
int getProgress() 获得当前网页的显示进度。
String getTitle() 获得当前网页的Title。
boolean pageDown(boolean bottom) 向下滚动视图大小的一半。
boolean pageUp(boolean top) 向上滚动视图大小的一半。
void reload() 重新加载当前网页。
void zoomBy(float zoomFactor) 指定网页缩放大小。
void requestFocus() 是页面获得焦点。

更详细的WebView API可查看官方文档:http://developer.android.com/reference/android/webkit/WebView.html

二. 申请访问互联网的权限

访问互联网需要申请INTERNET权限。可以在AndroidMainfest.xml文件中增加如下配置:

<uses-permission android:name="android.permission.INTERNET" />

三. 界面布局

WebView界面布局用<WebView>指定。

在activity_main.xml中:

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

四. 从url加载网页

(1)方法一:loadUrl()

在MainActivity.java中,使用loadUrl()访问网页,都是使用Android系统自带或第三方的浏览器来访问。

其中:

1)Web资源:webView.loadUrl("http://dengzhr.com");

2)本地文件用:webView.loadUrl("file:///andoroid_asset/XX.html");
(本地文件存放在assets文件中)

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;

public class MainActivity extends AppCompatActivity {
    // WebView访问的URL地址
    private String url = "http://ce.sysu.edu.cn/hope";

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

        // 获取WebView元素
        WebView myWebView = (WebView) findViewById(R.id.myWebView);
        // 加载url网页
        myWebView.loadUrl(url);
    }
}

(2)方法二: 使用URL Intent访问

使用Intent意图访问:

private String url = "http://ce.sysu.edu.cn/hope";

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

五. 加载HTML代码

WebView提供了loadData(String data, String mimeType, String encoding)方法,可以对HTML字符进行解析并解析出来。但是loadData()当加载包含中文的HTML内容时,会显示乱码。

loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)是loadData()方法的增强版,不会产生乱码。

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

String summary = "<html><body>You scored <b>192</b> points.真棒!</body></html>";
myWebView.loadData(summary, "text/html", "utf-8");

// 或者使用loadDataWithBaseURL()
 myWebView.loadDataWithBaseURL(null, summary, "text/html", "utf-8", null);

六. 使用WebView中的JavaScript调用Android方法

为了让WebView中的JavaScript脚本调用Android方法,WebView提供了一个配套的WebSettings工具类,该工具类提供了大量的方法来管理WebView的选项设置,其中它的setJavaScriptEnabled(true)即可让WebView中的WebView中的JavaScript脚本来调用Android方法。

为了把Android对象暴露给WebView中的JavaScript代码,WebView提供了addJavaScriptInterface(Object object, String name)方法,该方法负责将object对象暴露给JavaScript中的name对象。

因此,在WebView的JavaScript中调用Android方法只要如下三个步骤:

  • (1) 调用WebView关联的WebSettings的setJavaScriptEnabled(true),启用JavaScript调用功能;
  • (2) 条用WebView的addJavaScriptInterface(Object object, String name)方法,将object对象暴露给JavaScript脚本;
  • (3) 在JavaScript脚本中,通过暴露的name对象调用Android方法。

实例:

MainActivity.java:

// 获取WebView元素对象
WebView myWebView = (WebView) findViewById(R.id.myWebView);
// 打开远程网页
myWebView.loadUrl("http://dengzhr.com/test.html");

// 获取WebView的设置对象
WebSettings webSettings = myWebView.getSettings();
// 开启JavaScript调用
webSettings.setJavaScriptEnabled(true);
// 将MyObj对象暴露给JavaScript脚本
myWebView.addJavascriptInterface(new MyObject(this), "myObj");

MyObject.java:

import android.app.AlertDialog;
import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

public class MyObject {

    Context mContext;
    MyObject(Context context) {
        this.mContext = context;
    }

    // 该方法将会暴露给JavaScript脚本调用
    @JavascriptInterface
    public void showToast(String name) {
        Toast.makeText(mContext, name + "您好!", Toast.LENGTH_LONG).show();
    }

    // 该方法将会暴露给JavaScript脚本调用
    @JavascriptInterface
    public void showList() {
        // 显示一个普通的列表对话框
        new AlertDialog.Builder(mContext)
                .setTitle("图书列表")
                .setIcon(R.mipmap.ic_launcher)
                .setItems(new String[] {"疯狂Android讲义",
                        "Android编程指南",
                        "Android和PHP开发实践",
                        "Android数据库应用编程"}, null)
                .setPositiveButton("确定", null)
                .create()
                .show();
    }
}

test.html:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content=" text/html; charset=utf-8" />
    <title>JS调用Android</title>
    <style>
        input[type=button] {
            font-size: 14px;
            line-height: 1.8;
               background: #249E78;
               border: 1px #ccc solid;
               color: #fff;
               margin: 0 10px;
        }
    </style>
</head>
<body>
<input type="button" value="打招呼" onclick="myObj.showToast('Hello, World!');" />
<input type="button" value="图书列表" onclick="myObj.showList();" /> 
</body>
</html>

效果图如下:

此处输入图片的描述

源码下载

此处输入图片的描述

七. 在APP中使用系统自带的浏览器引擎

当用户点击一个WebView中的页面的链接时,通常,是由系统自带的默认浏览器打开并加载目标URL。

但是,我们可以通过webView.setWebViewClient(new WebViewClient())方法来覆盖这一系统默认行为,那么链接就会在WebView中打开。

在WebViewClient主要帮助webView去处理一些页面控制和请求通知。

WebView myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.loadUrl("http://ce.sysu.edu.cn/hope");

myWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        // 不采用系统默认浏览器加载URL
        view.loadUrl(url);

        // 当返回true时,控制网页在WebView中打开
        // 当返回false时,控制网页在系统自带的或第三方的浏览器中打开
        return true;
    }
});

八. 后退与前进

默认情况下,当你在WebView中依次打开好几个网页时,如果想返回上一个网页,按返回键却会退出整个应用程序。显然,这样的用户体验确实挺糟糕的。

当你的WebView覆盖了URL加载,它会自动生成历史访问记录。你可以通过goBack()或goForward()向前或向后访问已访问过的站点。根据这一点,我们可以改写物理返回按键的返回逻辑,让它返回当前WebView网页栈的前一项即可。

在这里,我们在Activity下改写物理按键的返回逻辑:

// 改写按键的返回逻辑
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    // 当当前按键为返回键时
    if(keyCode == KeyEvent.KEYCODE_BACK) {

        // 如果当前WebView存在访问栈
        if(myWebView.canGoBack()) {
            // 返回页面的上一页
            myWebView.goBack();
            return true;
        }else {
            // 如果当前页为最初加载的页面时,则返回键退出程序
            System.exit(0);
        }
    }
    return super.onKeyDown(keyCode, event);
}

完整的代码如下:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    private WebView myWebView;
    private String myUrl = "http://dengzhr.com";

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

        myWebView = (WebView) findViewById(R.id.myWebView);
        myWebView.loadUrl(myUrl);

        myWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

                // 不采用系统默认浏览器加载URL
                view.loadUrl(url);

                // 当返回true时,控制网页在WebView中打开
                // 当返回false时,控制网页在系统自带的或第三方的浏览器中打开
                return true;
            }
        });
    }

    // 改写按键的返回逻辑
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        // 当当前按键为返回键时
        if(keyCode == KeyEvent.KEYCODE_BACK) {

            // 如果当前WebView存在访问栈
            if(myWebView.canGoBack()) {
                // 返回页面的上一页
                myWebView.goBack();
                return true;
            }else {
                // 如果当前页为最初加载的页面时,则返回键退出程序
                System.exit(0);
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}

九. 显示加载网页的进度条

在加载网页的过程中,如果当前网络信号不佳或者网页体积较大,页面会出现较长一段时间的空白。用户有可能在这较长时间的的等待中,以为当前网页无法加载而退出应用。这样,用户体验无疑是不佳的。

网络信号和网页体积都是我们所难以控制的。如果,能在用户等待网页加载的过程中,显示当前加载的进度,用户就能心中有数,并能更好地掌握当前页面的可访问性。为此,我们就需要去判断页面的加载过程,制作进度条给予用户良好的体验效果。

具体如下:

private WebView myWebView;
private String myUrl = "http://dengzhr.com";
private ProgressDialog dialog;

myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.loadUrl(myUrl);

// 设置在WebView中打开网页
myWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        // 不采用系统默认浏览器加载URL
        view.loadUrl(url);

        // 当返回true时,控制网页在WebView中打开
        // 当返回false时,控制网页在系统自带的或第三方的浏览器中打开
        return true;
    }
});

// 设置网页加载的进度条显示
myWebView.setWebChromeClient(new WebChromeClient() {

    @Override
    public void onProgressChanged(WebView view, int newProgress) {

         /*
         *newProgress 为1-100之间的整数
         * newProgress = 100时,意味着网页加载完毕
         * newProgress < 100时,意味着网页正在加载
         **/
        if(newProgress == 100) {
            // 网页加载完毕,关闭进度提示
            closeDialog();
        }else {
            // 网页正在加载
            openDialog(newProgress);
        }
    }

    // 关闭进度条
    private void closeDialog() {
        if(dialog != null && dialog.isShowing()) {
            dialog.dismiss();
            dialog =null;
        }
    }

    // 打开进度条,并设置进度条样式
    private void openDialog(int newProgress) {
        if(dialog == null) {
            dialog = new ProgressDialog(MainActivity.this);
            dialog.setTitle("正在加载...");
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setProgress(newProgress);
            dialog.show();
        }else {
            dialog.setProgress(newProgress);
        }
    }
});

此处输入图片的描述

源码下载

此处输入链接的描述

十. WebView缓存的运用

使用进度条来提醒用户当前的加载进度确实可以提高用户体验。但这种做法是治标不治本的,网页加载依然缓慢,响应性能依然不够好。

除了对网页进行网络请求加载和文件大小等优化以外,还可以通过使用缓存来减少网络请求,从而加快网页的响应。

WebView中缓存的设置:

1)优先使用缓存:webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

2)不使用缓存:webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

// WebView优先使用缓存加载
WebSettings settings = myWebView.getSettings();
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
本文作者:子匠_Zijor,转载请注明出处:http://www.dengzhr.com/others/mobile/695