目录
- 什么是 WebView?
- 基础用法
- 添加权限
- 在布局文件中添加 WebView
- 在 Activity/Fragment 中初始化和加载网页
- 核心功能与配置
- 启用/禁用 JavaScript
- 自定义 User-Agent
- 处理网页链接的跳转
- 处理网页加载状态
- 处理网页标题和图标
- 与 JavaScript 交互
- Android 调用 JavaScript 函数
- JavaScript 调用 Android 方法
- 高级功能与最佳实践
- 文件上传
- 处理 HTTPS 和混合内容
- 性能优化(多进程、缓存)
- 安全性(防止 XSS、CSRF)
- 处理返回键
- 常见问题与解决方案
- 网页白屏、加载失败
- 内存泄漏
- 加载速度慢
什么是 WebView?
WebView 是 Android SDK 中一个核心的组件,它基于 Chromium 项目,可以让你在你的 App 内部显示一个完整的网页浏览器界面。

主要用途:
- 加载网页: 直接加载在线的 URL 或本地的 HTML 文件。
- 混合开发: 作为 Hybrid App(混合应用)的容器,前端使用 HTML, CSS, JS 开发,通过 WebView 嵌入到原生 App 中。
- 展示富文本: 加载包含复杂格式(如图片、链接、列表)的 HTML 内容,比使用原生 TextView 更灵活。
基础用法
1 添加网络权限
在 AndroidManifest.xml 文件中,必须声明 INTERNET 权限,否则 WebView 无法加载网络内容。
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<!-- 如果需要加载本地文件,可能还需要 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Android 13 (API 33) 及以上需要 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<application ...>
...
</application>
</manifest>
2 在布局文件中添加 WebView
在你的 XML 布局文件中,添加一个 WebView 组件。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/my_webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
3 在 Activity/Fragment 中初始化和加载网页
在 Activity 或 Fragment 的 Java/Kotlin 代码中,获取 WebView 实例并进行配置。

import android.os.Bundle
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val webView = findViewById<WebView>(R.id.my_webview)
// 1. 启用 JavaScript (默认是关闭的)
webView.settings.javaScriptEnabled = true
// 2. 设置 WebViewClient,让网页在当前 WebView 中打开,而不是跳转到外部浏览器
webView.webViewClient = WebViewClient()
// 3. 加载网页
// 加载网络 URL
webView.loadUrl("https://www.google.com")
// 或者加载本地 HTML 文件
// webView.loadUrl("file:///android_asset/index.html")
}
}
关键点解释:
webView.settings.javaScriptEnabled = true: 必须开启,否则网页中的 JS 代码将无法执行。webView.webViewClient = WebViewClient(): 这是最关键的一步,如果你不设置它,点击网页中的链接时,系统会调用默认的浏览器来打开链接,而不是在你的 WebView 中。WebViewClient会处理所有的页面加载请求,让它们在内部完成。
核心功能与配置
1 处理网页加载状态
你可以通过设置 WebViewClient 的回调方法来监控网页的加载过程,例如显示/隐藏加载进度条。
webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
// 页面开始加载时,显示进度条
showProgressBar() // 自定义方法
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
// 页面加载完成时,隐藏进度条
hideProgressBar() // 自定义方法
}
}
2 处理网页链接的跳转
如果你想拦截所有链接点击事件,并自己决定如何处理(判断是否是外部链接),可以重写 shouldOverrideUrlLoading 方法。
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
val url = request?.url.toString()
// 示例:如果链接是 "myapp://..." 开头的,则由原生代码处理
if (url.startsWith("myapp://")) {
handleCustomScheme(url)
return true // 表示已处理,不再由 WebView 加载
}
// 对于其他所有链接,仍然在 WebView 中加载
return false // 表示由 WebView 默认处理
}
}
3 处理网页标题和图标
可以通过 WebChromeClient 来获取网页的标题和图标。

webView.webChromeClient = object : WebChromeClient() {
override fun onReceivedTitle(view: WebView?, title: String?) {
super.onReceivedTitle(view, title)
// 可以在这里更新 Activity 的标题
supportActionBar?.title = title
}
override fun onReceivedIcon(view: WebView?, icon: Bitmap?) {
super.onReceivedIcon(view, icon)
// 可以在这里获取网页的图标
}
}
与 JavaScript 交互
这是 WebView 最强大的功能之一。
1 Android 调用 JavaScript 函数
使用 evaluateJavascript 方法。
// 在 Android 端
val jsCode = "showNativeToast('Hello from Android!');"
webView.evaluateJavascript(jsCode) { value ->
// 这里的 value 是 JS 函数的返回值
Log.d("WebView", "JS returned: $value")
}
对应的 JavaScript 代码 (index.html):
function showNativeToast(message) {
// 调用 Android 端暴露的方法
if (window.androidInterface) {
window.androidInterface.showToast(message);
}
}
2 JavaScript 调用 Android 方法
这需要将一个 Java/Kotlin 对象“注入”到 JavaScript 的上下文中。
第一步:创建一个与 JS 交互的类
这个类需要是 public 的,并且其公共方法需要用 @JavascriptInterface 注解。
class WebAppInterface(private val context: Context) {
@JavascriptInterface
fun showToast(toast: String) {
Toast.makeText(context, toast, Toast.LENGTH_SHORT).show()
}
@JavascriptInterface
fun startNewActivity() {
val intent = Intent(context, SecondActivity::class.java)
context.startActivity(intent)
}
}
第二步:将对象注入到 WebView
// 在 Activity 中 val webView = findViewById<WebView>(R.id.my_webview) // ... 其他设置 // 将 WebAppInterface 对象注入到 JavaScript 的 "androidInterface" 对象中 webView.addJavascriptInterface(WebAppInterface(this), "androidInterface")
第三步:在 JavaScript 中调用
<!DOCTYPE html>
<html>
<head>
<script>
function callAndroid() {
window.androidInterface.showToast("Hello from JavaScript!");
window.androidInterface.startNewActivity();
}
</script>
</head>
<body>
<button onclick="callAndroid()">Call Android Method</button>
</body>
</html>
高级功能与最佳实践
1 文件上传
默认情况下,网页中的 <input type="file"> 是无法工作的,需要设置 WebChromeClient 并重写 onShowFileChooser 方法。
webView.webChromeClient = object : WebChromeClient() {
// ... 其他回调
// For Android 5.0 (Lollipop) and above
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
// 这里需要调用你的文件选择器代码,例如使用 Activity Result API
// 伪代码:
// launchFilePicker { uris ->
// filePathCallback?.onReceiveValue(uris)
// }
return true
}
}
2 处理 HTTPS 和混合内容
如果你的网页加载的是 HTTPS,但其中包含了 HTTP 资源(混合内容),默认情况下 WebView 可能会阻止加载。
可以在 settings 中设置:
// 允许加载混合内容 webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_MODE_ALWAYS_ALLOW
3 性能优化
- 启用硬件加速: 在
AndroidManifest.xml中为你的 Activity 或 Application 标签添加android:hardwareAccelerated="true"。 - 使用多进程: 对于性能要求高的 WebView,可以考虑在独立的进程中运行它,以避免影响主线程,在
AndroidManifest.xml中为 Activity 声明android:process。 - 缓存管理:
webView.settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK// 优先使用缓存,没有再从网络加载- 在不需要时清除缓存:
webView.clearCache(true)
4 安全性
@JavascriptInterface注解: 极其重要! 从 Android 4.2 (API 17) 开始,所有被注入到 JS 的方法必须添加@JavascriptInterface注解,否则无法从 JS 访问,这可以有效防止恶意 JS 代码调用你的原生代码。- 禁用不必要的功能: 如果你的页面不需要文件上传,可以考虑禁用相关功能。
- HTTPS: 始终优先使用 HTTPS 来保护数据传输安全。
5 处理返回键
当用户按下返回键时,应该让 WebView 返回上一页,而不是直接退出 Activity。
override fun onBackPressed() {
if (webView.canGoBack()) {
webView.goBack()
} else {
super.onBackPressed()
}
}
常见问题与解决方案
1 网页白屏、加载失败
- 检查网络权限: 确保已在
AndroidManifest.xml中添加了INTERNET权限。 - 检查 URL: 确认 URL 是否正确。
- 检查 WebViewClient: 确保设置了
WebViewClient,否则链接会跳转到外部浏览器导致页面加载不完整。 - 检查 JS 错误: 在网页开发者工具中查看是否有 JS 错误导致页面无法渲染。
- 检查混合内容: 如果是 HTTPS 页面加载 HTTP 资源,尝试设置
mixedContentMode。
2 内存泄漏
这是 WebView 最常见的问题,WebView 的生命周期管理不当,很容易导致内存泄漏。
- 在 Activity/Fragment 的
onDestroy()或onDestroyView()中销毁 WebView。 - 最佳实践:
override fun onDestroy() {
// 如果是 Fragment,在 onDetach() 中做类似操作
webView.parent?.let {
(it as ViewGroup).removeView(webView)
}
webView.destroy()
super.onDestroy()
}
3 加载速度慢
- 优化网页本身: 压缩图片、合并 CSS/JS 文件、使用 CDN。
- 使用缓存: 合理设置
cacheMode。 - 预加载: 如果可能,在后台提前加载 WebView。
- 多进程: 如前所述,将 WebView 放在独立进程中。
WebView 是连接原生 Android 应用和 Web 世界的强大桥梁,掌握它的基本用法、JS 交互、性能优化和安全注意事项,对于成为一名合格的 Android 开发者至关重要。
核心要点回顾:
- 加权限:
INTERNET。 - 开 JS:
settings.javaScriptEnabled = true。 - 留网页:
webView.webViewClient = WebViewClient()。 - 防泄漏:
onDestroy()中webView.destroy()。 - 保安全:
@JavascriptInterface注解必不可少。
希望这份详细的指南能帮助你更好地在 Android 开发中使用 WebView!
