Android 使用WebView

来源:互联网 发布:linux avi 转mp4 编辑:程序博客网 时间:2024/06/06 09:13

概述:

如果一个 APP需要访问Web, 我们可以使用WebView. WebView类是Android的View类的子类, 它让我们可以以activity的layout形式显示网页. 它不包括一个完整开发的web浏览器的任何功能, 比如导航控制, 或者地址栏. 所有WebView做的事情, 默认情况下就只是显示一个网页. 

一个常用的使用WebView的场景就是当我们想要在APP内提供更新相关信息的时候, 比如一个最终用户同意(同意xx协议)或者一个用户向导. 在Android APP内, 我们可以创建一个Activity包含一个WebView, 然后用它来显示我们的在线文档. 另一个使用WebView的场景就是如果我们的APP需要提供数据给用户并总是需要网络连接来获取数据的时候, 比如Email. 在这种情况下我们可能发现在Android APP中使用WebView来显示所有的用户数据比执行一个网络请求然后解析数据并显示在layout中更加简单. 下面的小节将会介绍如何使用WebView实现额外的功能, 比如处理页面导航和支持网页中的JavaScript.

为APP添加一个WebView:

想要向APP中添加一个WebView, 只要在Activity的layout中包含一个<WebView>标签就可以了. 栗子:

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

想要在WebView中加载一个网页的话, 使用loadUrl()方法, 栗子:

WebView myWebView = (WebView) findViewById(R.id.webview);myWebView.loadUrl("http://www.example.com");

在这些生效之前, 我们的APP必须拥有对网络的访问权限. 只需要这样就OK了:

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

如果想要WebView显示一个网页, 这就是所有我们需要做的了.

在WebView中使用JavaScript:

如果WebView即将加载的网页使用了JavaScript, 我们必须为WebView启用JavaScript. 启用之后, 我们就可以在APP和JavaScript代码之间创建接口了.

启用JavaScript:

JavaScript在WebView中默认是禁用的. 我们可以通过设置WebView中的WebSettings来启用它. 要获取WebSettings需要使用getSettings()方法, 然后用setJavaScriptEnabled()启用JavaScript.栗子:

WebView myWebView= (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

WebSettings提供了对多种设置项的访问. 比如可以使用setUserAgentString()来设置用户代理, 然后在网页中查询自定义用户代理来识别客户端是不是我们真正的APP, 还是其它的什么东西.

绑定JavaScript代码到Android代码:

当开发一个web app特别是WebView的时候, 我们可以在JavaScript代码和客户端Android代码之间创建接口. 比如, JavaScript代码可以调用一个Android代码中的方法来电视一个Dialog, 而不是使用JavaScript的alert()方法. 要在JavaScript和Android代码之间绑定一个新的接口, 需要调用addJavascriptInterface()方法, 并传入一个类实例来绑定到JavaScript,还有一个参数就是JavaScript可以调用的接口的名字. 比如, 我们可以包含这些类到Android APP中:

publicclass WebAppInterface{
    Context mContext;

    /** Instantiatethe interface and set the context */
    WebAppInterface(Context c){
        mContext = c;
    }

    /** Show a toastfrom the web page */
    @JavascriptInterface
    public void showToast(String toast){
        Toast.makeText(mContext, toast,Toast.LENGTH_SHORT).show();
    }
}

注意: 如果已经设置了targetSdkVersion为17或者更高, 我们必须添加@JavascriptInterface注解到任何想要在JavaScript中可用的方法前面, 该方法也必须为public. 如果不这么做, 那么在Android4.2及更高版本中网页就无法访问该方法.

在上面的栗子中, WebAppInterface类让网页可以通过showToast()方法来创建一个Toast消息. 我们可以使用addJavascriptInterface()绑定该类到JavaScript, 并将其命名为Android,栗子:

WebView webView = (WebView) findViewById(R.id.webview);webView.addJavascriptInterface(new WebAppInterface(this), "Android");

这为WebView中运行的JavaScript创建了一个叫做Android的接口. 此刻web app便拥有了访问WebAppInterface类的权限. 栗如, 这是一些HTML和使用showToast()方法的JavaScript代码:

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /><script type="text/javascript">    function showAndroidToast(toast) {        Android.showToast(toast);    }</script>

并不需要从JavaScript初始化Android接口. WebView将会自动使其对网页可用. 所以, 在点击button之后, showAndroidToast()方法使用Android接口来调用WebAppInterface.showToast()方法.

提醒: 绑定到JavaScript的对象将会运行在其它线程中而不是在构造它的线程中.

注意: 使用addJavascriptInterface()可以让JavaScript控制我们的APP. 这能提供很多便利, 提供强大的功能, 也可以引起危险的安全问题.当在WebView中的HTML不值得信任的时候(比如一部分或者全部的HTML由未知的对象提供的), 可以执行代码的HTML完全可以发起一次攻击. 正因为这样, 除非所有显示在WebView中的HTML和JavaScript都是我们自己写的, 否则不应该使用addJavascriptInterface(). 同理也应该阻止用户通过WebView导航到其它不是自己的网站的页面去. (默认情况下应该允许用户使用默认的系统浏览器访问外部网站).

处理页面导航:

当用户在WebView中点击一个连接的时候, Android的默认行为是加载一个APP来处理URL. 通常默认的网页浏览器会打开并加载目标地址. 但是我们可以为WebView重写这个行为, 让连接在WebView内部打开. 然后可以在WebView内部通过浏览记录来控制向前向后的导航. 要打开用户点击的连接, 只需要简单的使用setWebViewClient()向WebView提供一个WebViewClient即可, 栗子:

WebView myWebView = (WebView) findViewById(R.id.webview);myWebView.setWebViewClient(new WebViewClient());

这就是所有的代码了, 现在所有WebView内部的连接将会在WebView中打开. 如果想要更多的控制, 那么创建自己的WebViewClient并重写shouldOverrideUrlLoading()方法, 栗如:

private class MyWebViewClient extends WebViewClient {    @Override    public boolean shouldOverrideUrlLoading(WebView view, String url) {        if (Uri.parse(url).getHost().equals("www.example.com")) {            // This is my web site, so do not override; let my WebView load the page            return false;        }        // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));        startActivity(intent);        return true;    }}

然后为WebView创建一个新的WebViewClient的实例:

WebView myWebView = (WebView) findViewById(R.id.webview);myWebView.setWebViewClient(new MyWebViewClient());

现在当用户点击一个连接, 系统将会调用shouldOverrideUrlLoading(), 它会检查URL的域名是否满足指定的域名(就像上面定义的). 如果匹配了, 就返回false不重新加载URL(正常处理). 如果URL的host不匹配, 那么会创建一个新的intent,并启动默认的Activity来处理URL(使用用户默认的web浏览器).

导航网页历史:

当我们的WebView重写了URL加载, 它会自动累积访问历史. 我们可以通过goBack()和goForward()方法来在访问历史中执行向前或者向后操作. 栗如, 这里是Activity中使用设备的返回按钮实现向后导航的操作:

@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {    // Check if the key event was the Back button and if there's history    if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {        myWebView.goBack();        return true;    }    // If it wasn't the Back key or there's no web page history, bubble up to the default    // system behavior (probably exit the activity)    return super.onKeyDown(keyCode, event);}

如果有访问历史可以用, 那么canGoBack()方法会返回true. 同样我们可以使用canGoForward()方法来检查是否可以向前. 如果不执行这个检查, 那么一旦用户到达了历史记录的尽头, goBack()和goForward()方法将会什么也不做.

 

参考: https://developer.android.com/guide/webapps/webview.html

0 0