Bitwebc 是一个基于 Android WebView 的增强库,使用 Kotlin DSL 进行配置。它提供统一的加载进度、错误页、生命周期与事件流,并支持可选的文件选择与下载能力,便于在 App 内快速集成 H5 页面。
Gradle 引入(JitPack)
在 settings.gradle.kts 中:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}在模块的 build.gradle.kts 中(将 Tag 替换为上方徽章显示的最新版本号,如 v0.1.0 或 0.1.0):
dependencies {
implementation("com.github.0xddy:Bitwebc:Tag")
}环境要求
- Android minSdk 24+
- Kotlin 1.9+ / Java 11+
- AndroidX
项目采用多模块结构,可按需引入。
通过 JitPack 引入(仓库已发布到 JitPack 时)
- 在工程根目录的
settings.gradle.kts的dependencyResolutionManagement.repositories中加入 JitPack:
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}- 在需要使用 WebView 的模块的
build.gradle.kts中按模块引入(将版本号替换为实际值):
dependencies {
implementation("com.github.0xddy.Bitwebc:bitwebc-core:版本号")
implementation("com.github.0xddy.Bitwebc:bitwebc-filechooser:版本号") // 可选
implementation("com.github.0xddy.Bitwebc:bitwebc-download:版本号") // 可选
// 以及 androidx.webkit、core-ktx、appcompat、coroutines 等,见方式一
}版本号可使用 GitHub 的 Release 标签(如 1.0.0)、提交 hash 或 main-SNAPSHOT(分支最新快照)。
说明
bitwebc-core为必选,提供 WebView 容器、DSL 配置、进度条、错误页、事件与 JSBridge 等。bitwebc-filechooser、bitwebc-download为可选;不引入时,文件选择/下载相关能力不会生效,需自行通过registerFileChooserHandler/registerDownloadHandler注册实现,或忽略对应能力。
先完成「只打开一个网页」的集成,再逐步加功能。
1. 布局中放入 WebView 容器
在 Activity 的布局里使用 BitwebcView 作为 WebView 的容器(全屏示例):
<?xml version="1.0" encoding="utf-8"?>
<cn.lmcw.bitwebc.core.ui.BitwebcView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bitwebc_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />2. 在 Activity 中配置并加载 URL
在 onCreate 中获取 BitwebcView,调用 setup,在 DSL 里至少指定要加载的地址即可:
import androidx.appcompat.app.AppCompatActivity
import cn.lmcw.bitwebc.core.ui.BitwebcView
class MainActivity : AppCompatActivity() {
private var session: BitwebcSession? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bitwebcView = findViewById<BitwebcView>(R.id.bitwebc_view)
session = bitwebcView.setup(this) {
loadUrl("https://example.com")
}
}
override fun onDestroy() {
session?.release()
session = null
super.onDestroy()
}
}setup { } 会返回 BitwebcSession,用于后续控制 WebView 和释放资源;在 onDestroy 中调用 session?.release() 即可。
至此,你已经完成最小集成:打开页面、自带加载进度条、返回键会先尝试 WebView 后退。
在 setup { } 的闭包内可以链式增加以下配置。
1. 自定义错误页
加载失败时展示自定义视图,并指定「重试」按钮和错误信息文案的 ViewId:
val customErrorView = LayoutInflater.from(this)
.inflate(R.layout.view_web_error, bitwebcView, false)
session = bitwebcView.setup(this) {
loadUrl("https://example.com")
errorPage(
errorView = customErrorView,
retryViewId = R.id.btn_retry,
errorMessageViewId = R.id.tv_error_message
)
}错误页布局需包含:一个根视图、重试按钮(如 btn_retry)、用于显示错误信息的 TextView(如 tv_error_message)。库会在加载失败时显示该视图,点击重试会重新加载当前 URL。
2. WebView 设置
通过 settings { } 配置 WebSettings,例如:
settings {
javaScriptEnabled = true
domStorageEnabled = true
databaseEnabled = true
loadWithOverviewMode = true
useWideViewPort = true
supportZoom = false
builtInZoomControls = false
displayZoomControls = false
allowFileAccess = false
userAgentSuffix = "MyApp/1.0"
cacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK)
disableScrollBars()
disableLongPressSelection()
}按需开启/关闭 JavaScript、存储、缩放、缓存等。
3. 进度条样式
通过 indicator { } 修改顶部进度条颜色和高度:
indicator {
color("#FF3B30")
heightDp(3)
}4. 拦截 URL(如自定义 Scheme)
通过 webViewInterceptor 传入自定义 WebViewClient,在 shouldOverrideUrlLoading 中处理特定链接(如 bitwebc://close 关闭页面):
webViewInterceptor(object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
): Boolean {
val url = request.url?.toString().orEmpty()
if (url.startsWith("bitwebc://close")) {
finish()
return true
}
return false
}
})BitwebcSession 提供 events: SharedFlow<BitwebcEvent>,可在协程中收集页面加载、下载、文件选择、全屏等事件。
在 Activity 中示例:
import cn.lmcw.bitwebc.core.event.BitwebcEvent
import kotlinx.coroutines.launch
lifecycleScope.launch {
session?.events?.collect { event ->
when (event) {
is BitwebcEvent.PageStarted -> { /* 页面开始加载 */ }
is BitwebcEvent.PageFinished -> { /* 页面加载完成 */ }
is BitwebcEvent.PageError -> { /* 加载错误 */ }
is BitwebcEvent.SslError -> { /* SSL 错误 */ }
is BitwebcEvent.DownloadQueued,
is BitwebcEvent.DownloadProgress,
is BitwebcEvent.DownloadSuccess,
is BitwebcEvent.DownloadFailed -> { /* 下载相关 */ }
is BitwebcEvent.FileChooserPermissionDenied,
is BitwebcEvent.FileChooserCancelled,
is BitwebcEvent.FileChooserFailed -> { /* 文件选择相关 */ }
is BitwebcEvent.FullscreenChanged -> { /* 全屏变化 */ }
is BitwebcEvent.SchemeFallback -> { /* 无法处理的 Scheme */ }
is BitwebcEvent.RenderProcessGone -> { /* 渲染进程退出 */ }
}
}
}也可使用 session?.addEventListener(listener) 注册 BitwebcEventListener,按需二选一。
1. 定义 Bridge 对象
用 @JavascriptInterface 标注需要暴露给前端的方法:
import android.webkit.JavascriptInterface
class MyJsBridge(private val context: Context) {
@JavascriptInterface
fun showToast(message: String) {
Toast.makeText(context, "JS->Native: $message", Toast.LENGTH_SHORT).show()
}
}2. 在 setup 中注册
通过 jsBridge(name, bridge) 注册,前端通过 window[name].methodName() 调用:
val myBridge = MyJsBridge(this)
session = bitwebcView.setup(this) {
loadUrl("https://example.com")
jsBridge("BitwebcApp", myBridge)
}前端示例:window.BitwebcApp.showToast('hello')。
3. Native 调用 JS
在获得 WebView 后,可使用扩展方法安全执行 JS(如页面加载完成后通知前端):
import cn.lmcw.bitwebc.core.bridge.evaluateJavascriptSafe
session?.webView?.postDelayed({
session?.webView?.evaluateJavascriptSafe(
"typeof window.onNativeReady === 'function' && window.onNativeReady('ready');"
)
}, 800L)若已依赖 bitwebc-download,可在 setup 中注册下载处理器;否则需要自行实现 DownloadHandler 并注册。
1. 使用内置下载模块(带确认弹窗)
import cn.lmcw.bitwebc.download.BitwebcDownloadFactory
import cn.lmcw.bitwebc.download.config.DownloadConfig
import cn.lmcw.bitwebc.download.ui.DownloadConfirmUi
registerDownloadHandler { activity ->
BitwebcDownloadFactory.create(
activity,
DownloadConfig(
confirmBeforeDownload = true,
confirmUi = DownloadConfirmUi { act, request, onDecision ->
AlertDialog.Builder(act)
.setTitle("下载确认")
.setMessage("确认下载:${request.url.take(80)}...")
.setPositiveButton("下载") { _, _ -> onDecision(true) }
.setNegativeButton("取消") { _, _ -> onDecision(false) }
.setOnCancelListener { onDecision(false) }
.show()
}
)
)
}2. 不弹窗直接下载
将 confirmBeforeDownload = false,并可不传 confirmUi(或传默认实现)。
H5 中 input[type=file] 会触发 Android 的 onShowFileChooser。若已依赖 bitwebc-filechooser,库会提供默认实现;也可自行实现 FileChooserHandler 并通过以下方式注册:
registerFileChooserHandler { activity ->
MyFileChooserHandler(activity)
}未依赖 filechooser 且未注册时,控制台会提示未解析到 FileChooserHandler,文件选择将不可用。
- SSL 错误策略:
sslErrorPolicy { url, error -> ... },返回true放行,false走默认拦截。 - WebMessagePort:
messagePorts { webView, receivePort, sendPort -> ... },用于与前端postMessage/ channel 通信。 - 资源拦截与离线包:在
settings { interceptors { assetsRoute("https://app.example.com/", "offline_pkg") } }中把指定 URL 前缀映射到 assets 目录。 - 池化与回收:
reuseWebViewFromPool(true)开启 WebView 池;poolRecycleOptions { clearCacheOnRecycle(enable = true, includeDisk = false) }控制回收时是否清缓存。 - 生命周期:
lifeCycle(lifeCycle)传入自定义WebLifecycle,在onAttach/onResume/onPause/onDestroy做扩展。 - 自定义 UI 弹窗:通过
nativeUiDelegate(webUIProvider)替换 JS 的 alert/confirm/prompt 等默认弹窗。
若页面是 Fragment,可把 BitwebcView 放在 Fragment 的布局中,用带 Fragment 的 setup 重载:
bitwebcView.setup(fragment) {
loadUrl("https://example.com")
}此时会使用 Fragment 的 viewLifecycleOwner 管理生命周期。
仓库中的 sample 模块演示了上述大部分能力:自定义错误页、URL 拦截、事件收集、JSBridge、下载确认、WebMessagePort、进度条与池化等。可直接运行 sample 查看效果,并对照 MainActivity.kt 与布局文件做对照学习。
GitHub Actions(工作流 Release & Sample)
- Release:打标签
v*或 Run workflow 手动运行 → 上传三个 AAR +bitwebc-sample-<VERSION_NAME>-debug.apk到 Releases。手动运行时可填版本号,留空则用gradle.properties的VERSION_NAME。 - Sample:推送
master/main(相关路径变更)时编译并上传 同名 APK 到 Artifacts(保留约 3 天);PR 仅编译、不上传。版本号与VERSION_NAME一致,与 Release 里 sample 包命名相同。
| 概念 | 说明 |
|---|---|
BitwebcView |
布局中使用的容器 View,通过 setup(activity/fragment) { } 配置并启动。 |
BitwebcSession |
setup 的返回值,持有 webView、events,以及 loadUrl、release、addEventListener 等。 |
BitwebcBuilder |
DSL 的构建器,在 setup { } 闭包内调用的 loadUrl、errorPage、settings 等均在其上配置。 |
BitwebcEvent |
密封类,包含 PageStarted/PageFinished/PageError、SslError、Download*、FileChooser*、FullscreenChanged、SchemeFallback、RenderProcessGone 等。 |
按「引入模块 → 最小集成 → 常用配置 → 事件与 JSBridge → 下载/文件选择 → 其它配置」的顺序逐步叠加,即可在现有工程中完成集成与扩展。