获取 Android WebView 新窗口 URL 的正确方法

获取 android webview 新窗口 url 的正确方法

本文档旨在解决 Android WebView 中 `onCreateWindow` 方法无法直接获取 `window.open()` 打开的新窗口 URL 的问题。通过重写 `WebViewClient` 的 `shouldOverrideUrlLoading` 方法,并结合 `WebChromeClient` 的 `onCreateWindow` 方法,提供了一种可靠的方案来捕获和处理新窗口的 URL,并提供了示例代码和配置说明。

在 Android WebView 开发中,WebChromeClient 的 onCreateWindow 方法用于处理 JavaScript 的 window.open() 调用,创建新的 WebView 窗口。然而,onCreateWindow 方法本身并不直接暴露新窗口的 URL。本文将介绍如何通过结合 WebChromeClient 和 WebViewClient 来获取并处理新窗口的 URL。

解决方案:利用 shouldOverrideUrlLoading 拦截 URL

核心思路是利用 WebViewClient 的 shouldOverrideUrlLoading 方法拦截新窗口的 URL 请求。当 window.open() 被调用时,新的 WebView 会尝试加载 URL,此时 shouldOverrideUrlLoading 方法会被触发,从而可以获取到 URL。

以下是具体的实现步骤:

配置 WebView 设置:

首先,确保 WebView 启用了 JavaScript,并允许 JavaScript 打开新窗口,同时支持多窗口。

webView.apply {    settings.javaScriptEnabled = true    settings.javaScriptCanOpenWindowsAutomatically = true    settings.setSupportMultipleWindows(true)}

实现 WebChromeClient 的 onCreateWindow 方法:

在 onCreateWindow 方法中,创建一个新的 WebView,并设置自定义的 WebViewClient。

webChromeClient = object : WebChromeClient() {    override fun onCloseWindow(window: WebView?) {        super.onCloseWindow(window)    }    override fun onCreateWindow(        view: WebView?,        isDialog: Boolean,        isUserGesture: Boolean,        resultMsg: Message?    ): Boolean {        if (view?.context == null) {            return false        }        if (resultMsg == null) {            return false        }        // Use CustomTabs to open the link when the hitTestResult is not null        if (view.hitTestResult.extra != null) {            val colorParam = CustomTabColorSchemeParams.Builder().setToolbarColor(getColor(context, R.color.blue)).build()            val intent = CustomTabsIntent.Builder()                .setDefaultColorSchemeParams(colorParam)                .setShowTitle(true)                .build()            intent.launchUrl(view.context, Uri.parse(view.hitTestResult.extra))            return false        }        // Use a new webViewClient to handle window.open() case        val newWebView = WebView(view.context)        newWebView.webViewClient = object : WebViewClient() {            override fun shouldOverrideUrlLoading(                view: WebView?,                request: WebResourceRequest?            ): Boolean {                if (request?.url == null) {                    return true                }                val url = request.url.toString()                if (url.contains("example.com")) {                    // Here you can handle “example.com” and do whatever you want                    return true                }                return true            }        }        val transport = resultMsg.obj as WebView.WebViewTransport        transport.webView = newWebView        resultMsg.sendToTarget()        return true    }}

实现 WebViewClient 的 shouldOverrideUrlLoading 方法:

在自定义的 WebViewClient 中,重写 shouldOverrideUrlLoading 方法。在该方法中,可以获取到新窗口的 URL,并进行相应的处理。

newWebView.webViewClient = object : WebViewClient() {    override fun shouldOverrideUrlLoading(        view: WebView?,        request: WebResourceRequest?    ): Boolean {        if (request?.url == null) {            return true        }        val url = request.url.toString()        if (url.contains("example.com")) {            // 在这里处理包含 "example.com" 的 URL            // 例如,打开一个新的 Activity 显示该 URL            return true        }        return true    }}

代码解释

settings.javaScriptEnabled = true: 启用 JavaScript。settings.javaScriptCanOpenWindowsAutomatically = true: 允许 JavaScript 自动打开窗口。settings.setSupportMultipleWindows(true): 支持多窗口。onCreateWindow: 创建新窗口的回调,在这里创建新的 WebView 并设置 WebViewClient。shouldOverrideUrlLoading: 拦截 URL 加载请求,在这里获取 URL 并进行处理。

注意事项

安全问题: 启用 JavaScript 可能会引入安全风险,需要谨慎处理用户输入和加载的 URL。性能问题: 创建过多的 WebView 可能会影响性能,需要合理管理 WebView 的生命周期。URL 处理: 在 shouldOverrideUrlLoading 方法中,需要根据实际需求处理 URL。可以打开新的 Activity 显示 URL,或者执行其他操作。Context 兼容性: 确保在创建 WebView 时使用正确的 Context,避免内存泄漏。CustomTabs 的使用: 代码中使用了 CustomTabs 来打开链接,需要引入相应的依赖,并处理好兼容性问题。如果 view.hitTestResult.extra 不为空,表示用户点击了链接,此时使用 CustomTabs 打开链接可以提供更好的用户体验。

总结

通过结合 WebChromeClient 的 onCreateWindow 方法和 WebViewClient 的 shouldOverrideUrlLoading 方法,可以有效地获取并处理 Android WebView 中 window.open() 打开的新窗口 URL。这种方法简单易用,可以满足大多数场景的需求。在实际应用中,需要根据具体情况进行调整和优化,以确保安全性和性能。

以上就是获取 Android WebView 新窗口 URL 的正确方法的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1531328.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
C++ 模板在实际开发中常见应用有哪些?
上一篇 2026年5月10日 10:53:47
CSS3实现预载动画效果的几种方法
下一篇 2026年5月10日 10:53:47

相关推荐

  • 以太坊和比特币的区别_主要差异在哪里

    比特币是去中心化电子现金,专注价值存储与转移;以太坊是可编程平台,支持智能合约与去中心化应用,二者在定位、技术与生态上根本不同。 以太坊和比特币:不仅仅是数字资产的差异 当人们谈论加密世界时,比特币和以太坊是两个无法绕开的名字。虽然它们常常被并列提及,但实际上,两者在设计哲学、核心功能和未来愿景上存…

    2026年5月10日
    000
  • 使用JS动态生成HTML时如何管理状态_使用JS动态生成HTML时如何管理状态策略

    答案:管理JavaScript动态生成HTML的状态需以数据驱动UI。1. 使用单一数据源确保状态集中,如将用户信息存于对象中,更新时先改数据再重新渲染;2. 封装状态与逻辑,用类组织数据和方法,调用方法后自动刷新视图;3. 借鉴响应式模式,通过Proxy监听状态变化并自动更新界面;4. 避免频繁直…

    2026年5月10日
    000
  • php数据库如何实现增删改查 php数据库基本操作的综合教程

    使用PDO实现PHP数据库操作,需通过预处理语句执行增删改查。1. 连接数据库时设置DSN和异常模式;2. 插入数据使用prepare与execute防止SQL注入;3. 查询用fetchAll或fetch获取结果;4. 更新和删除同样采用预处理绑定参数,确保安全。核心是始终使用预处理机制避免拼接S…

    2026年5月10日
    000
  • c++中decltype关键字的用法 _c++ decltype关键字解析

    decltype 是 C++11 关键字,用于编译时推导表达式类型,包含引用和 const 限定符;其规则分三种情况:标识符或成员访问返回声明类型,加括号的表达式视为左值返回 T&,函数调用或右值返回确切类型但不带引用;常用于模板、泛型编程和尾置返回类型,如 decltype(t + u) …

    2026年5月10日
    000
  • python进程的交流方式

    Python中进程间通信主要有四种方式:1. multiprocessing.Queue支持跨进程安全的数据传递,适用于多生产者消费者场景;2. multiprocessing.Pipe提供双向通信通道,适合两个进程间的点对点高效通信;3. Value和Array通过共享内存实现简单数据类型共享,性…

    2026年5月10日
    000
  • 非关联元素悬停交互:使用JavaScript动态调整DIV亮度

    本文详细介绍了如何通过javascript实现对非关联html元素进行悬停交互效果,具体演示了当鼠标悬停在一个`div`上时,如何动态改变另一个`div`的亮度。教程涵盖了html结构、javascript事件监听与css `filter`属性的应用,并提供了完整的代码示例、平滑过渡效果的实现以及最…

    2026年5月10日
    000
  • Golang如何配置环境以支持Go get_Golang依赖下载与环境配置全攻略

    正确配置Go环境并启用Modules是使用go get的前提。需安装Go并设置GOROOT、GOPATH和PATH;在项目根目录执行go mod init初始化模块;通过go get下载依赖,建议配置GOPROXY代理如https://goproxy.cn以加速国内下载;遇到问题时检查包名、代理设置…

    2026年5月10日
    000
  • Python网络爬虫:应对动态CSS类名选择的策略

    在Python网络爬虫中,面对现代网站动态生成的随机CSS类名(如media-story-card__body__3tRWy)是常见挑战。本文将详细介绍如何利用CSS属性选择器,特别是“以…开头”的选择器([attribute^=”value”]),来有效定位这些…

    2026年5月10日
    100
  • 解决Laravel Tinker工厂创建数据错误:代码变更不生效与类型转换陷阱

    本文探讨了在使用Laravel Tinker通过工厂创建数据时常见的错误,特别是“数组到字符串转换”和类型不匹配问题。核心原因在于Tinker会缓存应用状态,导致代码变更后不立即生效。文章将详细解释这些问题,提供解决方案,并分享使用Tinker进行开发和调试的最佳实践,强调在修改代码后重启Tinke…

    2026年5月10日
    000
  • Go语言:不使用 flags 包获取命令行参数的实践

    本文将深入探讨在Go语言中,如何在不依赖标准库flags包的情况下,直接获取和处理命令行参数。通过使用os.Args,开发者可以访问程序启动时传入的原始参数切片,这对于实现自定义的、符合特定规范(如GNU风格)的命令行解析器至关重要。文章将提供详细的代码示例,并解析os.Args的结构与应用场景,帮…

    2026年5月10日
    000
  • 将React组件转换为Qwik组件:qwik-react 的使用与考量

    本文旨在阐述如何使用 `qwik-react` 将 React 组件集成到 Qwik 应用中。我们将深入探讨 `qwikify$` 的作用机制,分析其在迁移 React 应用到 Qwik 时的优势与局限性,并强调过度使用 `qwikify$` 可能带来的性能问题。同时,本文还将讨论在 Qwik 项目…

    2026年5月10日
    000
  • 解决 Carbon::parse 无法解析复杂数据结构中的日期时间字符串问题

    本教程详细阐述了在使用 carbon 解析日期时间时,如何处理来自数据库查询结果或 json 字符串等复杂数据结构中嵌套的 `created_at` 字段。文章将通过示例代码演示如何正确提取日期时间字符串,并将其转换为 carbon 实例,从而避免常见的解析错误,并顺利进行日期时间操作,如添加天数和…

    2026年5月10日
    000
  • Python字典数据结构优化与值提取教程

    本文旨在指导python初学者如何优化字典数据结构,以避免不必要的嵌套,并实现高效的值提取与数据处理。通过分析常见的数据结构设计误区,我们将展示如何构建简洁且功能强大的字典,从而简化后续的数据操作,如排序,并提升代码的可读性和维护性。 在Python编程中,字典(Dictionary)是一种非常灵活…

    2026年5月10日
    000
  • Go database/sql 中自定义 []byte 类型扫描异常及解决方案

    本文探讨go语言中自定义`[]byte`类型在与`database/sql`包交互时可能遇到的一个常见陷阱。当使用`sql.rows.scan`将数据库结果扫描到自定义`[]byte`类型时,若不进行显式类型断言,可能导致数据意外丢失或行为异常。文章将深入分析其原因,并提供通过显式类型转换解决此问题…

    2026年5月10日
    000
  • 外部CSS怎么链接到HTML页面_外部CSS链接到HTML页面的详细说明

    使用外部CSS文件可提升代码维护性与复用性。一、通过link标签在HTML的head中引入CSS,设置rel=”stylesheet”、href指向文件路径,推荐使用。二、利用@import指令导入CSS,可在style标签或CSS文件中使用,但会延迟加载,影响性能。三、通过…

    2026年5月10日
    000
  • 使用Flexbox和JavaScript实现动态布局切换与内部元素重排

    本教程详细阐述如何利用CSS Flexbox和JavaScript实现网页布局的动态切换,包括主容器的垂直/水平方向调整,以及内部文本输入框的同步重排。通过精心设计的HTML结构、CSS样式和JavaScript逻辑,我们能够创建一个响应式且用户友好的界面,允许用户根据需求灵活切换内容展示方式,确保…

    2026年5月10日
    100
  • PHP动态网页CSV文件导入_PHP动态网页CSV数据文件导入处理指南

    在日常的Web应用开发中,我们经常会遇到需要从外部导入数据的情况,其中CSV文件因其简洁和通用性,成为了最常见的选择。但别看它只是纯文本,实际处理起来,从文件上传、解析、数据清洗到最终入库,每一步都藏着不少细节和挑战。说白了,就是把用户扔过来的一个文本表格,安全、准确地塞进我们的数据库里。 要实现P…

    2026年5月10日
    000
  • 解决预训练RetinaNet模型结果不确定性的问题

    本文旨在解决在使用预训练RetinaNet模型进行推理时,出现结果不确定性的问题。通过添加随机种子,确保代码在相同输入下产生一致的输出。文章详细介绍了如何在PyTorch中设置随机种子,包括针对CPU、CUDA、NumPy以及Python内置的random模块,并提供了示例代码进行演示。同时,还讨论…

    2026年5月10日
    000
  • React Router与Firebase认证:构建安全保护路由的实践指南

    本文深入探讨了在React应用中使用React Router和Firebase Authentication实现保护路由时常见的无限重定向问题。核心在于组件初次渲染时认证状态未就绪,导致误判。通过引入useEffect钩子监听Firebase认证状态变化,并结合加载状态管理,可以有效解决这一问题,确…

    2026年5月10日
    100
  • c++如何调用C语言编写的函数_C++与C语言混合编程方法

    C++调用C函数需用extern “C”避免名称修饰,确保C函数用C编译器编译,并在C++中正确声明和链接目标文件或库。 在实际开发中,C++调用C语言函数是一种常见的混合编程需求。由于C++支持函数重载、名称修饰(name mangling)等特性,而C语言没有,直接调用可…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信