Android WebView 与 H5 双向通信实现详解

WebView与Android原生通信 阅读详情
AI摘要

本文详细介绍 Android 原生应用中 WebView 与 H5 页面双向通信的完整方案。涵盖 H5 端和 Android 端实现、Activity 使用及布局文件。还提及实现要点,包括安全、性能、调试和兼容性处理,给出最佳实践建议和注意事项,可按需扩展优化。

Android WebView 与 H5 双向通信实现详解

背景介绍

在 Android 原生应用中,WebView 与 H5 页面的双向通信是一个常见需求。本文将详细介绍如何实现一个完整的通信方案。

核心实现

1. H5 端实现

与之前类似,但需要针对 Android 环境做适配:

window.ntalkCallbacks = {
  callbacks: {},
  
  register: function(type, successCallback, errorCallback) {
    const callbackId = type + Date.now().toString();
    
    // Promise方式
    if (!successCallback && !errorCallback) {
      const promise = new Promise((resolve, reject) => {
        this.callbacks[callbackId] = {
          success: resolve,
          error: reject,
        };
      });
      return {
        promise,
        callbackId
      };
    }
    
    // 回调方式
    this.callbacks[callbackId] = {
      success: successCallback, 
      error: errorCallback,
    };
    return callbackId;
  },

  execute: function(callbackId, type, data) {
    const callback = this.callbacks[callbackId];
    if (callback) {
      if (type === 'success') {
        callback.success && callback.success(data);
      } else {
        callback.error && callback.error(data);
      }
      delete this.callbacks[callbackId];
    }
  }
};

// Android桥接对象
window.ntalkNative = {
  getUserInfo: function(successCallback, errorCallback) {
    const callbackId = ntalkCallbacks.register('getUserInfo', successCallback, errorCallback);
    // 调用Android注入的对象
    window.androidBridge.postMessage(JSON.stringify({
      type: 'getUserInfo',
      callbackId,
      data: null
    }));
  },

  getUserInfoAsync: async function() {
    const { promise, callbackId } = ntalkCallbacks.register('getUserInfo');
    window.androidBridge.postMessage(JSON.stringify({
      type: 'getUserInfo',
      callbackId,
      data: null
    }));
    return promise;
  }
};

2. Android 端实现

class WebViewBridge(private val webView: WebView) {
    
    // JavaScript接口类
    @JavascriptInterface
    class AndroidBridge(private val handler: Handler, private val bridge: WebViewBridge) {
        @JavascriptInterface
        fun postMessage(message: String) {
            // 切换到主线程处理
            handler.post {
                bridge.handleMessage(message)
            }
        }
    }

    init {
        setupWebView()
    }

    private fun setupWebView() {
        webView.apply {
            settings.apply {
                javaScriptEnabled = true
                domStorageEnabled = true
            }
            
            // 注入JavaScript接口
            addJavascriptInterface(
                AndroidBridge(Handler(Looper.getMainLooper()), this@WebViewBridge),
                "androidBridge"
            )
        }
    }

    private fun handleMessage(message: String) {
        try {
            val jsonObject = JSONObject(message)
            val type = jsonObject.getString("type")
            val callbackId = jsonObject.getString("callbackId")
            val data = jsonObject.opt("data")

            when (type) {
                "getUserInfo" -> handleGetUserInfo(callbackId)
                "setAppCache" -> handleSetAppCache(callbackId, data)
                else -> sendCallback(callbackId, "error", "Unknown type")
            }
        } catch (e: Exception) {
            Log.e("WebViewBridge", "Handle message error", e)
        }
    }

    private fun sendCallback(callbackId: String, type: String, data: Any?) {
        val script = """
            window.ntalkCallbacks.execute(
                '$callbackId',
                '$type',
                ${Gson().toJson(data)}
            );
        """.trimIndent()
        
        webView.evaluateJavascript(script, null)
    }

    private fun handleGetUserInfo(callbackId: String) {
        try {
            // 示例:获取用户信息
            val userInfo = mapOf(
                "userId" to "123",
                "name" to "张三",
                "avatar" to "https://example.com/avatar.png"
            )
            sendCallback(callbackId, "success", userInfo)
        } catch (e: Exception) {
            sendCallback(callbackId, "error", e.message)
        }
    }

    private fun handleSetAppCache(callbackId: String, data: Any?) {
        try {
            // 处理缓存逻辑
            sendCallback(callbackId, "success", true)
        } catch (e: Exception) {
            sendCallback(callbackId, "error", e.message)
        }
    }
}

3. Activity 中使用

class WebViewActivity : AppCompatActivity() {
    
    private lateinit var webView: WebView
    private lateinit var webViewBridge: WebViewBridge

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_webview)

        webView = findViewById(R.id.webView)
        webViewBridge = WebViewBridge(webView)

        setupWebView()
    }

    private fun setupWebView() {
        webView.apply {
            webViewClient = object : WebViewClient() {
                override fun onPageFinished(view: WebView?, url: String?) {
                    super.onPageFinished(view, url)
                    // 页面加载完成后的处理
                }
            }

            webChromeClient = object : WebChromeClient() {
                override fun onConsoleMessage(message: ConsoleMessage): Boolean {
                    Log.d("WebView", "${message.message()} -- From line ${message.lineNumber()} of ${message.sourceId()}")
                    return true
                }
            }

            // 加载网页
            loadUrl("https://example.com")
        }
    }

    override fun onDestroy() {
        webView.destroy()
        super.onDestroy()
    }
}

4. 布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

实现要点

  1. 安全性考虑

    • 使用 @JavascriptInterface 注解标记可供 JS 调用的方法
    • 处理跨线程调用问题
    • 注意 WebView 内存泄漏问题
  2. 性能优化

    • 使用 Handler 确保在主线程处理 UI 操作
    • 避免频繁的 JSON 解析和字符串操作
    • 合理管理 WebView 生命周期
  3. 调试功能

    • 实现 WebChromeClient 以捕获 console 日志
    • 添加详细的错误日志
    • 支持开发环境调试
  4. 兼容性处理

    • 处理不同 Android 版本的兼容性问题
    • 确保 JavaScript 接口注入的稳定性
    • 处理 WebView 内核版本差异

最佳实践建议

  1. 添加通信超时机制
  2. 实现错误重试策略
  3. 添加网络状态监听
  4. 实现页面加载进度提示
  5. 处理 WebView 内存管理
  6. 添加安全域名白名单
  7. 实现离线缓存策略

注意事项

  1. 在 AndroidManifest.xml 中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
  1. 在 proguard-rules.pro 中添加混淆规则:
-keepclassmembers class com.example.webview.WebViewBridge$AndroidBridge {
    public *;
}
  1. 注意处理 WebView 的生命周期,避免内存泄漏。

这个实现方案提供了一个完整的 Android WebView 与 H5 通信框架,可以根据实际项目需求进行扩展和优化。

Android开发之——Android和WebView相互调用,干货 **@description:android调用js无参函数*//**@description:android调用js带参函数*//**@description:js调用android无参函数*//**@description:js调用android带参函数*//**@description:android调用js无参函数*//**@description:android调用js带参函数*//**@description:js调用android无参函数。 阅读详情

相关推荐

Flutter 混合开发:WebView 与原生完美融合实战

在移动应用开发中,纯原生(Native)或纯Flutter开发虽能提供优质体验,但面对“高频迭代的运营活动页”“复杂H5功能复用”“多端统一维护”等场景时,混合开发(Flutter + WebView)成为更优选择。本文聚焦“Flutter与WebView的深度融合”,覆盖集成流程、双向通信实现、性能优化及跨平台适配,帮助开发者快速上手实战。本文从“为什么需要混合开发”切入,逐步讲解核心概念(Flutter、WebView、双向通信)、集成步骤、通信实现、实战案例,最后总结常见问题与未来趋势。

架构师的AI之路,分享AI应用开发架构的学习与实践。 381

WebView使用详解、H5网页视频全屏播放 、网页跳转空白

转载请注明出处:https://blog.youkuaiyun.com/mr_leixiansheng/article/details/81000035 内容:介绍webview的使用方法,介绍WebViewClient、WebChromeClient,H5网页视频全屏播放,网页跳转空白问题 最近做项目老爱和H5打交道,遇到了很多问题也踩了许多坑,今天在这儿总结下,方便后人乘凉。 关于安卓和H5交互...

Mr_Leixiansheng的博客 6858

UniApp三端WebView通信实战:鸿蒙Next与安卓/iOS差异处理指南

本文详细解析了在UniApp中实现安卓、iOS与鸿蒙Next三端WebView双向通信的实战方案。针对鸿蒙Next平台因架构差异导致的API不同、消息格式不一致等核心问题,提供了具体的代码实现、条件编译策略和统一封装方案,并分享了调试技巧与性能优化建议,帮助开发者高效处理跨平台通信差异。

5b6n7m8的博客 317

Android WebView和H5交互总结

本文附带了一点H5和JS的内容,所以需要有基本的JS知识。学习JS基本知识可以看菜鸟教程。我自己也看过总结了一下知识点我会写一个简单的demo,且demo不需要联网全程本地操作,在文章末尾贴上所有代码。

wodongx123的博客 3760

uniapp中web-view组件实现App与H5双向通信的实战指南

本文详细介绍了uniapp中web-view组件实现App与H5双向通信的实战方法,包括URL传参和postMessage两种通信方式,以及安全校验、性能优化等进阶技巧。通过具体代码示例和项目结构解析,帮助开发者快速掌握混合应用开发中的核心通信技术,提升应用交互体验。

weixin_29001327的博客 117

从扫码到数据同步:实战解析uniapp中webview与原生APP的双向通信

本文详细解析了uniapp中webview与原生APP的双向通信实现方法,重点介绍了通过uni.postMessage和evalJS实现数据同步的技术方案。以扫码功能为例,展示了从网页触发原生功能到结果回传的完整流程,并提供了通信延迟、数据格式处理等常见问题的解决方案,帮助开发者高效实现混合开发。

weixin_29002595的博客 184

【webview】原生 App 与 H5 双向通信完全指南:JSBridge 原理与实战

本文系统介绍了Hybrid App中H5与原生双向通信的完整解决方案。通过分析Android和iOS底层通信原理(对象注入与消息通道),设计了一套跨平台JSBridge封装,统一调用接口并支持Promise异步处理。文章提供了双平台原生实现代码(Kotlin/Swift)和通用JSBridge模块(bridge.js),包含自动环境检测、回调管理、内存优化等核心功能。实战示例展示了同步/异步调用方式,并总结了生产环境中的常见问题与规避方案。该方案有效屏蔽平台差异,简化业务层开发,可直接应用于实际项目。

G.E.M.千百度的博客 452

跨端通信实战:解锁uniapp中webview与H5/APP的高效数据交互

本文详细介绍了uniapp中webview与H5/APP的高效数据交互方案,包括uni.postMessage和URL Schemes等通信方式。通过实战案例和高级技巧,帮助开发者解决跨端通信中的常见问题,提升混合应用开发效率。

weixin_27070451的博客 306

app和h5通讯

JSBridge 是一个开源库(如 GitHub 的 xinyuanhe/JsBridge),用于实现 Android WebView 与 JavaScript 的双向通信,支持 Native 调用 JS 方法或 JS 调用原生功能(如摄像头、支付)。以下是详细解析:概念与核心作用。

m0_47999208的博客 456

UniApp WebView通信实战:手把手教你实现H5唤起APP页面并传参(仿单点登录流程)

本文详细介绍了UniApp中WebView与H5页面通信的两种主流技术方案:uni.postMessage和URL Schemes。通过实战代码示例,展示了如何实现H5页面唤起APP并传递参数,包括电商活动页和第三方授权登录等常见场景。文章还提供了安全加固、性能优化及跨平台兼容性处理等进阶技巧,帮助开发者构建稳定高效的通信机制。

weixin_42558257的博客 305

别再问怎么监听H5页面跳转了!UniApp Web-View组件监听URL变化的两种实战方案(含uni.webview.js通讯)

本文深入探讨了UniApp中Web-View组件监听H5页面URL变化的两种实战方案,包括HTML5+原生监听和uni.webview.js通信方案。通过详细的技术原理、核心代码和性能优化措施,帮助开发者解决混合应用开发中的URL监控难题,提升支付流程、页面统计等场景的可靠性。

weixin_28730131的博客 397

Android WebView调用H5摄像头扫码全链路实现指南

WebView调用H5摄像头属于混合开发中的典型硬件能力透传场景,其本质是原生权限控制、Web媒体API(getUserMedia)、JSBridge通信三者协同的系统性工程。理解Android运行时权限模型与WebView安全策略,掌握MediaStream生命周期管理及跨层事件回调机制,是实现稳定扫码的基础技术前提。该方案广泛应用于电商核销、政务身份认证、企业OA等需轻量级扫码的App内嵌H5场景,尤其适合规避第三方SDK依赖、满足隐私合规与离线部署需求的中大型项目。本文聚焦Android 8–14真机

weixin_28273593的博客 160

uniapp微信小程序H5页面分享功能实现方案

在混合应用开发中,H5页面与原生小程序的通信是实现复杂功能的关键技术点。通过微信JS-SDK和小程序webview的配合,开发者可以构建双向通信机制,解决H5页面无法直接调用原生API的限制。这种技术方案特别适用于电商类小程序,能够实现活动页面的社交分享功能,提升用户裂变传播效果。其中,uniapp框架提供的uni.webview API与微信的wx.miniProgram接口形成桥接层,确保H5页面触发的事件能正确传递到小程序环境。实际应用中需要注意环境检测、参数传递和多端兼容等问题,同时结合性能优化和安

weixin_29281941的博客 233

WebView与Android原生交互实战:JSBridge封装与踩坑总结

移动端混合开发中,WebView与原生代码的双向通信是构建稳定Hybrid架构的核心环节。无论是H5调用原生能力,还是原生主动推送数据,都依赖一套可靠的消息桥接机制。文章从底层原理切入,对比addJavascriptInterface注入、URL拦截等主流方案,解析回调链路、线程安全与生命周期管理等关键技术点,并结合线上项目经验梳理内存泄漏、时序竞争等高频问题。通过协议设计、安全校验与降级策略,工程师可在Flutter、RN等跨端方案盛行的当下,依然为业务方提供高可用的H5交互通道。本文适合移动端开发者与前

weixin_34214500的博客 279

Android进阶之路 - 通过WebView与H5前端进行完美交互

快速掌握Andorid端的混合开发技能,可在Android中调用Js方法,也可以在Js中调用Android方法,加油~

Android、前端、小程序、后端 1万+

基于H5的中医舌诊安卓源码:WebView与JSBridge集成实战

在移动端图像采集场景中,WebView与原生混合开发能有效解决多机型色彩还原与相机适配问题。通过JSBridge实现H5与Java层双向通信,结合Base64传输与HSV色彩空间转换,可完成舌象图像的预处理与特征提取。这套方案将采集、上传、展示、记录串成完整链路,适用于中医健康类App的安卓开发、快速搭建舌诊Demo,以及Java课程设计或毕业设计参考。

weixin_33841722的博客 282

uniapp H5与APP通信全攻略:手把手教你实现webview双向数据传递(附避坑指南)

本文详细解析了uniapp框架下H5与APP通过webview实现双向通信的全过程,包括通信机制原理、基础配置实战、高级应用场景及调试技巧。特别针对iOS和Android平台的差异提供了解决方案,并分享了性能优化和安全加固策略,帮助开发者高效实现跨平台数据传递。

weixin_30505225的博客 420

Android WebView调用H5摄像头扫码实战指南

WebView摄像头扫码本质是WebRTC与原生能力协同的技术实践,其核心在于打通Android权限管理、MediaDevices API支持与H5视频流处理链路。原理上需配置WebSettings启用JavaScript/DOM存储/媒体访问,并通过WebChromeClient响应运行时权限请求;技术价值体现在免集成Camera SDK、降低APK体积、快速迭代扫码逻辑;典型应用于企业工单录入、设备绑定、审批单扫描等轻量级现场作业场景。本文聚焦Android 5.0+环境下WebView与H5协同调用摄

weixin_27014595的博客 236
上一篇: H5 与 WebView 的双向通信实现详解
下一篇: 人工智能界的“黑话“大揭秘:AI新词汇速成指南
wakangda
博客等级 码龄8年 445粉丝 96原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值