如果要将Web应用程序(或仅仅是网页)作为客户端应用程序的一部分提供,则可以使用WebView执行此操作。 WebView类是Android的View类的扩展,允许您将Web页面显示为活动布局的一部分。它不包括完全开发的Web浏览器的任何功能,例如导航控件或地址栏。默认情况下,WebView所做的就是显示一个网页。
本文档向您展示了如何开始使用WebView以及如何执行其他操作,例如处理页面导航以及将网页中的JavaScript绑定到Android应用程序中的客户端代码。
一、将WebView添加到您的应用程序
要将WebView添加到应用程序,可以在活动布局中包含<WebView>元素,也可以将整个“活动”窗口设置为onCreate()中的WebView。
在活动布局中添加WebView
将以下代码添加到活动的布局XML文件中:
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
要在WebView中加载网页,请使用loadUrl()。 例如:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");
在onCreate()中添加WebView
在活动的onCreate()方法中向您的应用添加WebView:
WebView myWebView = new WebView(activityContext);
setContentView(myWebView);
然后加载页面:
myWebView.loadUrl("https://www.example.com");
或者从HTML字符串加载URL:
// Create an unencoded HTML string
// then convert the unencoded HTML string into bytes, encode
// it with Base64, and load the data.
String unencodedHtml =
"<html><body>'%23' is the percent code for ‘#‘ </body></html>";
String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(),
Base64.NO_PADDING);
myWebView.loadData(encodedHtml, "text/html", "base64");
注意:此
HTML可以执行的操作有一些限制。 有关编码选项的详细信息,请参阅loadData()和loadDataWithBaseURL()。
权限
在此之前,您的应用必须能够访问Internet。 请在清单文件中请求INTERNET权限:
<manifest ... >
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>
这就是显示网页的基本WebView所需的全部内容。 此外,您可以通过修改以下内容来自定义WebView:
- 使用
WebChromeClient启用全屏支持。 当WebView需要更改主机应用程序UI的权限时,也会调用此类,例如创建或关闭窗口以及向用户发送JavaScript对话框。 - 处理影响内容呈现的事件,例如表单提交上的错误或使用
WebViewClient导航。 您还可以使用此子类来拦截URL加载。 - 通过修改
WebSettings启用JavaScript。 - 使用
JavaScript访问已注入WebView的Android框架对象。
二、在WebView中使用JavaScript
如果您计划在WebView中加载的网页使用JavaScript,则必须为WebView启用JavaScript。 启用JavaScript后,您还可以在应用代码和JavaScript代码之间创建接口。
启用JavaScript
默认情况下,在WebView中禁用JavaScript。
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
WebSettings提供对您可能会发现有用的各种其他设置的访问。 例如,如果您正在开发专门为Android应用程序中的WebView设计的Web应用程序,则可以使用setUserAgentString()定义自定义用户代理字符串,然后在网页中查询自定义用户代理以验证,请求您的网页的客户实际上是您的Android应用。
将JavaScript代码绑定到Android代码
在开发专为Web应用程序中的WebView设计的Web应用程序时,您可以在JavaScript代码和客户端Android代码之间创建接口。 例如,您的JavaScript代码可以调用Android代码中的方法来显示Dialog,而不是使用JavaScript的alert()函数。
要绑定JavaScript和Android代码之间的新接口,请调用addJavascriptInterface(),向其传递一个类实例以绑定到您的JavaScript以及您可以调用以访问该类的接口名称。
例如,您可以在Android应用中包含以下类:
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可用的任何方法(该方法也必须是公共的)。 如果您未提供注释,则在Android 4.2或更高版本上运行时,您的网页无法访问该方法。
在此示例中,WebAppInterface类允许网页使用showToast()方法创建Toast消息。
您可以使用addJavascriptInterface()将此类绑定到在WebView中运行的JavaScript,并将接口命名为Android。 例如:
WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
这将在WebView中创建一个名为Android for JavaScript的界面。 此时,您的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,也可能包括攻击者选择的任何代码。 因此,除非您编写了WebView中显示的所有HTML和JavaScript,否则不应使用addJavascriptInterface()。 您也不应允许用户在WebView中导航到不属于您自己的其他网页(而是允许用户的默认浏览器应用程序打开外部链接 - 默认情况下,用户的Web浏览器会打开所有URL链接,因此 只有在按照以下部分所述处理页面导航时才要小心)。
三、处理页面导航
当用户从WebView中的网页单击链接时,Android的默认行为是启动处理URL的应用程序。 通常,默认Web浏览器会打开并加载目标URL。 但是,您可以为WebView覆盖此行为,以便在WebView中打开链接。 然后,您可以允许用户在WebView维护的网页历史记录中前后导航。
注意:出于安全考虑,系统的浏览器应用程序不会与您的应用共享其应用程序数据。
要打开用户单击的链接,请使用setWebViewClient()为WebView提供WebViewClient。 例如:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(MyWebViewClient);
现在,用户在WebView中单击加载的所有链接。
如果您想要更好地控制单击链接的加载位置,请创建自己的WebViewClient来覆盖shouldOverrideUrlLoading()方法。 例如:
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading( WebView view, String url) {
if (Uri.parse(url).getHost().equals("https://www.example.com")) {
// This is my website, 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以启动处理URL的默认活动(解析为用户的默认Web浏览器)。
浏览网页历史记录
当WebView覆盖URL加载时,它会自动累积访问过的网页的历史记录。 您可以使用goBack()和goForward()在历史记录中前后导航。
例如,以下是您的Activity如何使用设备后退按钮向后导航:
@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);
}
}
如果实际存在用户要访问的网页历史记录,则canGoBack()方法返回true。 同样,您可以使用canGoForward()来检查是否存在转发历史记录。 如果您不执行此检查,那么一旦用户到达历史记录的末尾,goBack()或goForward()就不会执行任何操作。
处理设备配置更改
在运行时期间,当设备的配置发生更改(例如,用户旋转设备或关闭输入法编辑器(IME)时)会发生活动状态更改。 这些更改将导致销毁WebView对象的活动并创建新活动,这也会创建一个新的WebView对象,该对象将加载销毁对象的URL。 要修改活动的默认行为,您可以更改其在清单中处理方向更改的方式。
四、管理窗口
默认情况下,将忽略打开新窗口的请求。 无论是通过JavaScript还是通过链接中的target属性打开它都是如此。 您可以自定义WebChromeClient以提供打开多个窗口的行为。
警告:为了使您的应用更安全,最好防止弹出窗口和新窗口打开。 实现此行为的最安全方法是将“
true”传递给setSupportMultipleWindows(),但不覆盖setSupportMultipleWindows()依赖的onCreateWindow()方法。 但请记住,此逻辑还会阻止任何在其链接中使用target =“_ blank”的页面加载。