Android开发之webview简单使用技巧
前言
如果您希望在客户端应用中提供 Web 应用(或只是网页),则可以使用 WebView 执行该操作。WebView 类是 Android 的 View 类的扩展,可让您将网页显示为 Activity 布局的一部分。它不会包含功能全面的网络浏览器的任何功能,例如导航控件或地址栏。WebView 默认只显示网页。
使用 WebView 非常有用的一种常见情形是,您希望在应用中提供可能需要更新的信息,例如最终用户协议或用户指南。在 Android 应用中,您可以创建一个包含 WebView 的 Activity,然后使用它来显示在线托管的文档。
另一种 WebView 可能会有所帮助的情形是,如果您的应用向用户提供始终需要互联网连接才能检索数据的数据(例如电子邮件)。在这种情况下,您可能会发现相比于执行网络请求,然后解析数据并在 Android 布局中呈现数据,在 Android 应用中编译 WebView 以显示包含所有用户数据的网页更加轻松。您可以改为设计一个专为 Android 设备定制的网页,然后在加载该网页的 Android 应用中实现 WebView。
本文档向您介绍了如何开始使用 WebView 以及如何执行其他操作,例如处理网页导航以及将网页中的 JavaScript 绑定到 Android 应用中的客户端代码。
向应用中添加Webview
要向应用中添加 WebView,您可以在 Activity 布局中添加 元素,或在 onCreate() 中将整个 Activity 窗口设置为 WebView。
1.在 Activity 布局中添加 WebView
要在布局中为应用添加 WebView,请将以下代码添加到 Activity 的布局 XML 文件中:
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
要在 WebView 中加载网页,请使用 loadUrl()。例如:
val myWebView: WebView = findViewById(R.id.webview)
myWebView.loadUrl("http://www.example.com")
2.在 onCreate() 中添加 WebView
要在 Activity 的 onCreate() 方法中向应用添加 WebView,请使用类似如下的逻辑:
val myWebView = WebView(activityContext)
setContentView(myWebView)
然后使用以下命令加载网页:
myWebView.loadUrl("http://www.example.com")
或者通过 HTML 字符串加载网址:
// Create an unencoded HTML string
// then convert the unencoded HTML string into bytes, encode
// it with Base64, and load the data.
val unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"
val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING)
myWebView.loadData(encodedHtml, "text/html", "base64")
记得再此之前配置网络权限:
<manifest ... >
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>
以上就是用于显示网页的基本 WebView 所需的全部内容。此外,您还可以通过修改以下内容来自定义 WebView:
- 使用 WebChromeClient 启用全屏支持。如果 WebView 需要权限以更改主机应用的界面(例如创建或关闭窗口以及向用户发送 JavaScript 对话框),也需要调用此类。要详细了解如何在这种情况下进行调试;
- 处理影响内容呈现的事件,例如提交表单时或使用 WebViewClient 导航时出现的错误。 您也可以使用此子类拦截网址加载。
- 通过修改 WebSettings 来启用 JavaScript。
- 使用 JavaScript 访问已注入到 WebView 的 Android 框架对象。
在 WebView 中使用 JavaScript
如果您打算在 WebView 中加载的网页使用 JavaScript,则必须为您的 启用 JavaScript。启用 JavaScript 后,您还可以在应用代码和 JavaScript 代码之间创建接口。
启用 JavaScript
JavaScript 在 WebView 中默认处于停用状态。您可以通过附加到 WebView 的 WebSettings 启用 JavaScript。您也可以使用 getSettings() 检索 WebSettings,然后使用 setJavaScriptEnabled() 启用 JavaScript。
val myWebView: WebView = findViewById(R.id.webview)
myWebView.settings.javaScriptEnabled = true
WebSettings 提供对其他各种实用设置的访问权限。例如,如果您正在开发专为 Android 应用中的 WebView 设计的 Web 应用,则可以使用 setUserAgentString() 定义自定义用户代理字符串,然后在网页中查询自定义用户代理,以验证请求网页的客户端实际上是您的 Android 应用。
将 JavaScript 代码绑定到 Android 代码
在开发专为 Android 应用中的 WebView 设计的 Web 应用时,您可以在 JavaScript 代码和客户端 Android 代码之间创建接口。例如,您的 JavaScript 代码可以调用 Android 代码中的方法(而不是使用 JavaScript 的 alert() 函数)来显示 Dialog。
要绑定 JavaScript 代码与 Android 代码之间的新接口,请调用 addJavascriptInterface(),并传入类实例以绑定到 JavaScript 以及 JavaScript 可调用以访问类的接口名称。
例如,您可以在 Android 应用中包含以下类:
class WebAppInterface(private val mContext: Context) {
/**
* 弹Toast
*/
@JavascriptInterface
fun showToast(toast: String) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
}
}
注意:如果您将 targetSdkVersion 设置为 17 或更高,则必须向您希望 JavaScript(此方法也必须为公开方法)可用的任何方法添加 @JavascriptInterface 注释。如果您未提供注释,那么在 Android 4.2 或更高版本的平台上运行时您的网页将无法访问该方法。
在此示例中,WebAppInterface 类允许网页使用 showToast() 方法创建 Toast 消息。
您可以使用 addJavascriptInterface() 将此类绑定到在 WebView 中运行的 JavaScript,并为接口 Android 命名。例如:
val webView: WebView = findViewById(R.id.webview)
webView.addJavascriptInterface(WebAppInterface(this), "Android")
这会为在 WebView 中运行的 JavaScript 创建名为 Android 的接口。此时,您的 Web 应用可以访问 WebAppInterface 类。例如,以下是用于在用户点击按钮时使用新接口创建提示消息的 HTML 和 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 会自动将其提供给您的网页。因此,点击此按钮后,showAndroidToast() 函数会使用 Android 接口调用 WebAppInterface.showToast() 方法。
注意:绑定到 JavaScript 的对象在另一个线程中运行,而不是在构造它的线程中运行。
注意:使用 addJavascriptInterface() 可让 JavaScript 控制您的 Android 应用。这可能是非常实用的功能,也可能会造成危险的安全问题。如果 WebView 中的 HTML 不可信(例如,部分或全部 HTML 由未知人员或进程提供),则攻击者可以包含执行客户端代码的 HTML,并且可能包含攻击者选择的任何代码。因此,除非您编写了在 WebView 中显示的所有 HTML 和 JavaScript,否则请不要使用 addJavascriptInterface()。您也不应允许用户在您的 WebView 内导航到并非您自己的其他网页(而应允许用户的默认浏览器应用打开外部链接,默认情况下,用户的网络浏览器会打开所有网址链接,因此,请务必谨慎处理网页导航,如下文所述)。
处理网页导航
当用户在 WebView 中点击网页中的链接时,Android 的默认行为是启动处理网址的应用。默认网络浏览器通常会打开并加载目标网址。不过,您可以为 WebView 替换此行为,以便在 WebView 内打开链接。然后,您可以允许用户向后/向前浏览由您的 WebView 维护的网页历史记录。
注意:出于安全考虑,系统的浏览器应用不会与您的应用共享其应用数据。
要想在当前webview中打开用户点击的链接,请使用 setWebViewClient() 为您的 WebView 提供 WebViewClient。例如:
val myWebView: WebView = findViewById(R.id.webview)
myWebView.webViewClient = WebViewClient()
大功告成。现在,用户点击的所有链接都会在您的 WebView 中加载。
如果您希望更好地控制用户点击的链接的加载位置,请创建您自己的 WebViewClient 以替换 shouldOverrideUrlLoading() 方法。例如:
private class MyWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
if (Uri.parse(url).host == "www.example.com") {
// 这是我的网站,所以不要覆盖;让我的WebView加载页面
return false
}
// 否则,该链接不适合我网站上的页面,因此启动另一个处理URL的活动。
Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
startActivity(this)
}
return true
}
}
然后,为 WebView 创建这一新 WebViewClient 的实例:
val myWebView: WebView = findViewById(R.id.webview)
myWebView.webViewClient = MyWebViewClient()
现在,当用户点击某个链接时,系统会调用 shouldOverrideUrlLoading(),后者会检查网址主机是否与特定网域匹配(如上所述)。如果匹配,则该方法会返回 false,以避免替换网址加载(它允许 WebView 像往常一样加载网址)。如果网址主机不匹配,则创建 Intent 以启动用于处理网址的默认 Activity(解析为用户的默认网络浏览器)。
浏览网页历史记录
当您的 WebView 替换网址加载时,它会自动累积已访问网页的历史记录。您可以使用 goBack() 和 goForward() 向后/向前浏览历史记录。
例如,下面显示了您的 Activity 是如何使用设备的返回按钮向后导航的:
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
// 检查按键事件是否为“后退”按钮以及是否有历史记录
if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) {
myWebView.goBack()
return true
}
// 如果不是Back键或没有网页历史记录,则执行系统处理
return super.onKeyDown(keyCode, event)
}
如果确实存在用户要访问的网页历史记录,则 canGoBack() 方法会返回 true。同样,您可以使用 canGoForward() 检查是否存在向前历史记录。如果您不执行此检查,那么当用户浏览到历史记录的末尾时,goBack() 或 goForward() 将不执行任何操作。
处理设备状态更改
在运行时,Activity 状态更改会在设备的配置发生更改时发生,例如用户旋转设备或关闭输入法 (IME) 时。这些更改会导致 WebView 对象的 Activity 被销毁并创建新的 Activity,而这也会创建新的 WebView 对象来加载已销毁对象的网址。要修改 Activity 的默认行为,您可以在清单中更改其处理 orientation 更改的方式。
上一篇: django的url路由分发