专题 - Web应用->在WebView中创建Web应用

本篇文章翻译自Building Web Apps in WebView

如果你想分发一个web应用(或者只是一个web页面),其只是客户端app的一部分,你可以使用WebView来做到。WebView类是Android的View类的扩展,它允许你作为Activity布局的一部分来显示web页面。它不包括完全开发的web浏览器的任意特性,比如导航控制或者地址栏。WebView所做的,默认情况下,是显示一个web页面。

使用WebView的一个常见的有用的场景是,当你在你的app中想提供一些信息,而它们有可能需要更新,比如一个最终用户协议或者一个用户使用指南。在Android app中,你可以创建一个包含WebViewActivity,然后使用它来显示你的在线文档。

WebView可以带来帮助的另一个场景就是,如果你的app给用户提供的数据总是需要网络连接以获取数据,比如email。在这种情况下,你可能会发现在Android app中创建WebView来显示带有所有用户数据的web页面,要比发送网络请求然后解析数据并且在一个Android布局中渲染出来要简单得多。作为替代,你可以设计一个针对Android设备量身定做的web页面,并且在Android app中实现WebView来加载此页面。

这篇文档示例你如何开始使用WebView并且如何做一些附加的事情,比如在你的Android app中处理页面导航,将web页面中的JavaScript和客户端代码绑定起来。

在你的app中添加一个WebView

要在你的app中添加一个WebView,只需要简单地将WebView元素添加到你的activity的布局中即可。比如,这里是一个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中加载一个web页面,调用loadUrl。比如:

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

在上述代码可以工作之前,你的app需要可以访问网络。为了可以访问网络,在配置文件中声明INTERNET权限。比如:

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

对于一个显示web页面的基本WebView,这就是你所需要做的。

在WebView中使用JavaScript

如果你准备加载到WebView的web页面使用JavaScript,你必须为WebView开启JavaScript。当JavaScript启用后,你还可以在你的app代码与JavaScript代码之间创建借口。

启用JavaScript

WebView默认情况下是禁用JavaScript的。你可以通过附加在WebView上的WebSettings开启JavaScript。你可以使用getSettings()获取WebSettings,然后通过setJavaScriptEnabled()来启用JavaScript。

比如:

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

WebSettings提供了访问许多其它你可能觉得有用的设置的接口。比如,如果你在Android app开发了一个专为WebView设计的web app,你可以使用setUserAgentString()来定义一个自定义的用户代理,然后在你的web页面中查询自定义的用户代理来验证请求你的web页面的客户端实际上是你的Android app。

将JavaScript代码绑定到Android代码

当你在Android app里开发了一个专为WebView设计的web app时,你可以在JavaScript代码与客户端Android代码之间常见接口。比如,JavaScript代码可以调用Android代码中的一个方法来显示一个Dialog,而不是使用JavaScript的alert()方法。

要在JavaScript与Android代码之间绑定一个新的接口,可以调用addJavaScriptInterface()方法,传入一个类的实例来绑定到JavaScript和一个接口名,JavaScript通过它可以访问类。

比如,你可以将下面的类包含到你的Android app中:

public class WebAppInterface {
    Context mContext;

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

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

警告:如果你将targetSdkVersion设置为大于等于17,你必须将@JavascriptInterface注解加到任何你想要暴露给JavaScript的方法上(该方法同时必须是public的)。如果你没有提供该注解,当在Android 4.2或更高版本运行时,web页面则不能访问该方法。

在这个例子中,WebAppInterface类允许web页面使用showToast()方法创建一条Toast消息。

你可以使用addJavascriptInterface()方法并且将接口命名为Android,将该类绑定到在WebView中运行的JavaScript上。比如:

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

上面代码为运行在WebView中的JavaScript创建了一个名为Android的接口。在这个时候,你的web app就可以访问WebAppInterface类。比如,这里有一些HTML和JavaScript代码,当用户点击一个按钮时,它们创建了一条toast消息:

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>

这里没必要在JavaScript中初始化Android接口。WebView可以自动地使它对于你的web页面可用。所以,在点击按钮时,showAndroidToast()方法使用了Android接口来调用WebAppInterface.showToast()方法。

注意:绑定到JavaScript上的对象运行在另一个线程且不在创建它的那个线程。

警告:使用addJavascriptInterface()方法允许JavaScript控制你的Android app。这可以是一个很有用的特性或者是一个危险地安全问题。当WebView中的HTML不可信任时(比如,部分或者全部的HTML是由未知的人或者进程所提供),攻击者可以包含可以运行客户端代码的HTML代码,并且可能是攻击者选中的任意代码。正因如此,除非显示在WebView中的HTML和JavaScript全部都是你写的,否则不要使用addJavascriptInterface()。同样地,在你的WebView里,你也不要让用户可以导航到一个不是你自己的web页面(作为替代,默认情况下你可以允许用户的默认浏览器app打开外部链接,即使用用户的web浏览器打开所有URL链接,所以如果你处理页面导航时要小心,正如下面所描述的那样)。

处理页面导航

当用户在WebView的web页面里点击一个链接时,对于Android来说默认的行为是启动一个app来处理URL。通常,默认的web浏览器打开并且加载目标URL。但是,你可以为你的WebView覆盖这种行为,所以在WebView里可以代开这些链接。你可以允许用户在他们的web页面历史中前后导航,这由WebView来维护。

当用户点击后要打开链接,简单地使用setWebViewClient()方法为WebView提供一个WebViewClient即可。比如:

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

就是这样。现在用户点击的所有链接都会被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的逻辑(它允许WebView像往常一样加载URL)。如果URL的主机不符合,那么会创建一个Intent用于启动默认的Activity来处理URL(它会解析为用户的默认web浏览器)。

Web页面历史导航

当你的WebView覆盖URL加载时,它会自动将浏览过的web页面的历史累加起来。你可以使用goBack()goForward()在历史中向前和向后导航。

比如,这里是你的Activity使用设备的Back按钮向后导航:

@Override
public 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);
}

如何有web页面历史可供用户浏览,canGoBack()方法会返回true。同样的,你可以使用canGoForward()方法来检查是否有向前的历史。如果你不执行这项检查,那么一旦用户到达历史的尽头,goBack()goForward()将什么都不做。


回到专题 Web应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值