用WebView构建Web应用程序

来源:互联网 发布:怎么看自己的淘宝信誉 编辑:程序博客网 时间:2024/05/24 04:38

原始文章:https://developer.android.com/guide/webapps/webview.html#HandlingNavigation

如果您希望将web应用程序(或者只是一个web页面)作为客户机应用程序的一部分,您可以使用WebView来实现。WebView类是Android视图类的一个扩展,它允许您将web页面显示为活动布局的一部分。它不包括完全开发的web浏览器的任何特性,比如导航控件或地址栏。默认情况下,WebView所做的就是显示一个web页面。

使用WebView的一个常见场景是,当您希望在您的应用程序中提供您可能需要更新的信息时,例如最终用户协议或用户指南。在您的Android应用程序中,您可以创建一个包含WebView的活动,然后使用它来显示在线托管的文档。

WebView可以帮助的另一个场景是,如果您的应用程序向用户提供数据,那么它总是需要一个Internet连接来检索数据,比如电子邮件。在这种情况下,您可能会发现在Android应用程序中构建WebView更容易,它显示了包含所有用户数据的web页面,而不是执行网络请求,然后解析数据并将其呈现在Android布局中。相反,你可以设计一个为Android设备量身定制的网页,然后在你的Android应用程序中实现一个WebView,加载网页。

这个文档向您展示了如何开始使用WebView,以及如何做一些额外的事情,比如处理页面导航和将JavaScript从web页面绑定到Android应用程序中的客户端代码。

在应用程序中添加WebView

要向应用程序添加WebView,只需在活动布局中包含< WebView >元素。例如,这里有一个布局文件,其中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");

然而,在此之前,您的应用程序必须能够访问Internet。要获得互联网接入,请在您的清单文件中请求互联网权限。例如:

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

这就是显示网页的基本WebView所需要的全部内容

在WebView使用JavaScript

如果您计划在WebView中加载的web页面使用JavaScript,则必须为WebView启用JavaScript。一旦启用了JavaScript,您还可以在应用程序代码和JavaScript代码之间创建接口。

启用JavaScript

默认情况下,JavaScript在WebView中禁用。你可以通过WebView上的WebSettings来启用它。您可以使用getSettings()检索WebSettings,然后用setjavascritenabled()启用JavaScript。
例如:

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

WebSettings提供了对各种可能有用的其他设置的访问。例如,如果您正在开发一个web应用程序是专门为WebView在你的Android应用程序中,那么您可以定义一个自定义用户代理字符串setUserAgentString(),然后在您的web页面查询自定义用户代理来验证客户端请求web页面实际上是你的Android应用程序。

将JavaScript代码绑定到Android代码

在开发专门为Android应用程序的WebView设计的web应用程序时,可以在JavaScript代码和客户端Android代码之间创建接口。例如,JavaScript代码可以调用Android代码中的方法来显示对话框,而不是使用JavaScript的alert()函数。

要在JavaScript和Android代码之间绑定一个新接口,调用addJavascriptInterface(),传递一个类实例来绑定到您的JavaScript和一个接口名,您的JavaScript可以调用它来访问类。
例如,您可以在Android应用程序中包含以下类:

public class WebAppInterface {    Context mContext;    /** 实例化接口并设置上下文 */    WebAppInterface(Context c) {        mContext = c;    }    /** 在网页上展示Toast */    @JavascriptInterface    public void showToast(String toast) {        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();    }}

警告:如果您将targetSdkVersion设置为17或更高,那么您必须将@ javascriptinterface注释添加到您希望可用到JavaScript的任何方法(该方法也必须是公共的)。如果您不提供注释,那么在运行Android 4.2或更高版本时,您的web页面无法访问该方法。

在这个示例中,WebAppInterface类允许web页面使用showToast()方法创建Toast消息。
您可以使用addJavascriptInterface()将这个类绑定到运行在WebView中的JavaScript,并命名接口Android。例如:

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

这为WebView中运行的JavaScript创建了一个名为Android的实例。此时,您的web应用程序可以访问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会自动将它提供给你的网页。因此,在点击这个按钮时,showAndroidToast()函数使用Android接口调用WebAppInterface.showToast()方法。

注意:绑定到JavaScript的对象在另一个线程中运行,而不是在构建它的线程中运行。

注意:使用addJavascriptInterface()允许JavaScript控制Android应用程序。这可能是一个非常有用的特性,或者是一个危险的安全问题。当WebView中的HTML是不可信任的(例如,部分或全部HTML是由一个未知的人或进程提供的),那么攻击者就可以包含执行客户端代码的HTML,也可能包括攻击者选择的任何代码。因此,您不应该使用addJavascriptInterface(),除非您在WebView中编写了所有的HTML和JavaScript。你应该也不允许用户导航到其他不是自己的网页,在你的WebView(相反,在默认情况下允许用户的默认浏览器应用程序打开外国链接,用户的web浏览器打开所有URL链接,所以在处理像如下所述的导航页时要十分小心)。

处理页面导航

当用户单击WebView中web页面的链接时,默认行为是Android启动一个处理url的应用程序。通常,默认的web浏览器打开并加载目标URL。不过,您可以为WebView重写此行为,因此可以在WebView中打开链接。然后,您可以允许用户在他们的web页面历史中来回导航,这是由您的WebView维护的。

要打开用户点击的链接,只需为WebView提供一个WebViewClient,使用setWebViewClient()。例如:

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")) {            // 这是我的网站,所以不要重写;让我的WebView加载页面            return false;        }        // 否则,链接不在我的站点上的页面上,所以启动另一个Activity来处理url        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主机不匹配,则创建一个意图来启动处理URL的默认活动(该活动将解析到用户的默认web浏览器)

浏览网页的历史

当您的WebView覆盖URL加载时,它会自动地累积访问web页面的历史。您可以在goBack()和goForward()的历史中来回导航。

例如,下面是您的Activity可以使用设备的返回按键来实现后退导航:

@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {    // 检查按键事件是否是后退按键事件并且是否有历史记录    if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {        myWebView.goBack();        return true;    }    // 如果不是后退按键键,或者没有网页历史,那么冒泡到默认的系统行为(可能退出该活动)    return super.onKeyDown(keyCode, event);}

如果有实际的网页历史供用户访问,canGoBack()方法返回true。同样,您可以使用canGoForward()来检查是否有转发历史。如果您不执行此检查,那么一旦用户到达了历史的末尾,goBack()或goForward()什么也不做。