当前位置: 首页 > news >正文

webkitx(Android WebView 最佳实践库)--> 上

功能清单

  • WebView 基线设置(JS/存储/深色模式/Cookie)

  • Fragment 容器:BaseWebFragment

  • Activity 容器:BaseWebActivity

  • 导航与资源拦截SafeWebViewClient

    • http/https 内开、非 http(s) 外跳

    • 仅 API 路由注入请求头(Authorization)

    • 离线包路径映射(WebViewAssetLoader

  • UI/权限ChromeClientFragmentChromeClientActivity

    • 进度条、标题、<input type=file>、相机/麦克风权限钩子

  • 登录态TokenSync(推荐:Cookie 同步

  • 离线包热更新OfflineH5Manager(下载/校验/解压/切换/回滚)

  • 下载DownloadHelper + 系统 DownloadManager


1) 目录结构

webkitx/ ├─ build.gradle ├─ proguard-rules.pro ├─ src/main/ │ ├─ AndroidManifest.xml │ ├─ java/com/yourorg/webkitx/ │ │ ├─ WebViewHelper.kt │ │ ├─ TokenSync.kt │ │ ├─ OfflineH5Manager.kt │ │ ├─ SafeWebViewClient.kt │ │ ├─ ChromeClientFragment.kt │ │ ├─ ChromeClientActivity.kt │ │ ├─ BaseWebFragment.kt │ │ ├─ BaseWebActivity.kt │ │ └─ WebKitx.kt // 可选:全局开关 │ ├─ res/layout/fragment_webkitx.xml │ ├─ res/layout/activity_base_webkitx.xml │ ├─ res/xml/network_security_config.xml │ └─ assets/error/net_error.html


2) Gradle & 依赖

根 settings.gradle

include ':app', ':webkitx'

:webkitx/build.gradle

plugins { id 'com.android.library'; id 'org.jetbrains.kotlin.android' } android { namespace 'com.yourorg.webkitx' compileSdk 34 defaultConfig { minSdk 21 consumerProguardFiles 'proguard-rules.pro' } buildFeatures { viewBinding true } } dependencies { implementation "androidx.appcompat:appcompat:1.7.0" implementation "androidx.core:core-ktx:1.13.1" implementation "androidx.activity:activity-ktx:1.9.2" implementation "androidx.fragment:fragment-ktx:1.8.3" implementation "androidx.webkit:webkit:1.11.0" }

在 :app 中加入 implementation project(':webkitx')


3) 必要资源/配置(一键复制)

AndroidManifest.xml

<manifest> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:networkSecurityConfig="@xml/network_security_config" /> </manifest>

res/xml/network_security_config.xml(如需 http 调试域)

<network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">dev.yourdomain.com</domain> </domain-config> </network-security-config>

res/layout/fragment_webkitx.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/web_root" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/web" android:layout_width="match_parent" android:layout_height="match_parent"/> <ProgressBar android:id="@+id/progress" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="3dp" android:max="100" android:visibility="gone"/> <FrameLayout android:id="@+id/error_view" android:visibility="gone" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>

res/layout/activity_base_webkitx.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/web" android:layout_width="match_parent" android:layout_height="match_parent"/> <ProgressBar android:id="@+id/progress" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="3dp" android:max="100" android:visibility="gone"/> </FrameLayout>

assets/error/net_error.html

<!doctype html><meta charset="utf-8"><title>网络异常</title> <style>body{font-family:sans-serif;padding:24px}</style> <h2>网络开小差了</h2><p>请检查网络后重试</p>

proguard-rules.pro

-keep class android.webkit.** { *; } -keepclassmembers class * { @android.webkit.JavascriptInterface <methods>; } -dontwarn org.chromium.**


4) 关键类与职责(已实现)

  • WebViewHelper:初始化 WebSettings、深色模式、Cookie、调试

  • TokenSyncCookie 同步(推荐),附带 token() 占位

  • OfflineH5Manager:离线包下载/校验/解压/切换/回滚;暴露 currentDir() 与 hasBundle()

  • SafeWebViewClient:导航/拦截/SSL/错误;仅 API 路由注入请求头;离线包优先

  • ChromeClientFragment / ChromeClientActivity:进度/标题/文件选择(使用 ActivityResult)

  • DownloadHelper:系统 DownloadManager 下载 + 完成回调

  • BaseWebFragment:组合(Settings + Client + Chrome + Token + Offline)

  • BaseWebActivity:组合(同上)+ DownloadManager 集成

你只需要替换:白名单域名入口 URLTokenSync.token() 获取方式


5) 业务侧如何使用

A) Fragment 版(适合 ViewPager/Tab)

class WebHostActivity : AppCompatActivity(R.layout.activity_host) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val frag = BaseWebFragment( startUrl = "https://yourdomain.com/index.html", whiteHosts = setOf("yourdomain.com","api.yourdomain.com","cdn.yourdomain.com"), domainsForCookie = listOf("yourdomain.com","api.yourdomain.com"), offline = OfflineH5Manager(this), enableDebug = BuildConfig.DEBUG ) supportFragmentManager.beginTransaction() .replace(R.id.container, frag) .commit() } override fun onBackPressed() { val f = supportFragmentManager.findFragmentById(R.id.container) as? BaseWebFragment if (f?.canGoBack() == true) f.goBack() else super.onBackPressed() } }

B) Activity 版(简单直接)

class MyWebActivity : BaseWebActivity() { override fun startUrl() = "https://yourdomain.com/index.html" override fun whiteHosts() = setOf("yourdomain.com","api.yourdomain.com","cdn.yourdomain.com") override fun cookieDomains() = listOf("yourdomain.com","api.yourdomain.com") override fun offlineManager() = OfflineH5Manager(this) // 若启用离线包 }


6) 离线包更新(热更流程)

  1. 服务端提供 manifestversionzipUrlsha256

  2. App 下载 zip → offline.installFromZip(zip, version, sha256)

  3. 成功后 OfflineH5Manager.switchTo(version)(封装里已做)

  4. WebView 入口统一:

    • 在线:https://yourdomain.com/index.html

    • 离线:https://appassets.androidplatform.net/dynamic/index.html

  5. 如需回滚:offline.rollback()

BaseWebFragment/Activity 已根据 offline.hasBundle() 自动选择入口。


7) Token 注入策略(优先级)

  1. Cookie 同步(推荐)
    TokenSync.syncCookie(web, listOf("yourdomain.com","api.yourdomain.com"))
    后端从 Cookie 读取 AUTH_TOKEN

  2. 请求头注入(仅 API 路由)
    SafeWebViewClient.extraHeadersProvider = { mapOf("Authorization" to "Bearer ${TokenSync.token()}") }
    并通过 isApiPath(uri) 严格限制在 /api/**不要给静态资源加头

  3. JS 注入(备选)
    web.evaluateJavascript("window.__TOKEN__='${TokenSync.token()}';", null)


8) 下载(DownloadManager)

  • WebView 内部下载链接 → 交给系统 DownloadManager

  • 模块中已在 BaseWebActivity 里注册:

    • setDownloadListener{ url, ua, cd, mime, _ -> DownloadHelper.enqueue(...) }

    • 完成广播 DownloadHelper.registerCompletionReceiver(...)

Android Q+ 下载到公有 Downloads 目录无需手动存储权限;如需通知权限(Android 13+),在 App 动态申请 POST_NOTIFICATIONS


9) 扩展与开关

  • 域名白名单whiteHosts()

  • Cookie 同步域cookieDomains()

  • 仅 API 路由:在 SafeWebViewClient.isApiPath 中自定义

  • 调试WebViewHelper.init(web, enableDebug = BuildConfig.DEBUG)

  • 错误页error_view 自定义 UI;或加载 assets/error/net_error.html


10) 上线安全核查清单

  • onReceivedSslError() 一律 cancel(禁止放行自签证书)

  • 仅对 API 路由加请求头;禁止给静态资源加头

  • Scheme 外跳(weixin://alipays://tel:)留在白名单内显式处理

  • 仅在可信域注入 @JavascriptInterface(如后续要加 Bridge)

  • 生产关闭不必要的 mixedContent;能 https 就 https


11) 最少需要你改的 3 处

  1. 域名yourdomain.comwhiteHosts & cookieDomains

  2. 入口 URLstartUrl

  3. Token 获取:实现 TokenSync.token()

http://www.dtcms.com/a/558259.html

相关文章:

  • 怎么把文件发送到网站荣耀手机的商城在哪
  • 论文阅读:Multi-Spectral Image Color Reproduction
  • 怎样做元古建筑的网站结构图asp做素材网站
  • MongoDB Java:深入解析与应用实践
  • 有服务器和网站代码了 怎么建站ifm网站做啥的
  • Pikachu-国产轻量化 Web 漏洞靶场
  • 网站的域名每年都要续费手帐风格wordpress主题
  • 深入洞察:大模型推理能力及MindIE引擎
  • 番禺做网站哪家专业ppt怎么制作流程图
  • 多模态生成 Flamingo
  • Linux文件上传下载
  • 网站资料如何做脚注wordpress 注册 登录界面
  • 网站dns修改wordpress 该插件没有有效的标题
  • 2025年大湾区杯粤港澳金融数模竞赛B题完整数据集分享
  • 深圳市做网站知名公司有哪些创业平台是干什么的
  • 自动驾驶中的传感器技术24.2——Camera(17)
  • 【符号论】十二经络关系梳理
  • 网络原理——初识网络
  • 网站分站系统怎么申请域名和空间
  • 西安的电商平台网站建设深圳网站推广
  • 屏幕(2)
  • 网站策划包括哪些内容做是么网站
  • linux命令-安装-9
  • 告别重复图片!VisiPics 图片去重工具,高效清理存储空间
  • 哪个全球购网站做的好处ui设计师工作流程
  • WordPress站点地址填错wordpress地图怎么实现
  • pt网站怎么下载与做有什么做h5的网站
  • 南宁致峰网站建设网站架构分类
  • 04-Fiddler详解+抓包定位问题
  • 怎样建设一个公司网站wordpress页面相册