JockeyJS——优秀的WebView与JS交互开源库使用和解析

前端 | 本地调试H5页面方案总结 背景大学毕业快要一年了,用leader的话说我也是有一年开发经验的前端开发工程师了,输出是检验输入的最好方法,那我就慢慢来总结这一年来在工作中总结的经验教训,分享给大家,有不专业和不完善的地方,请大家多多指点反馈,比心~做过一段时间的运营需求,一些主要在手机上浏览的页面,遇到的最大问题是调试的问题: 对于简单的网络、APP环境的调试,我们可以通过Chrome调试安卓机上的H5页面,通过Safari调 阅读详情

前言

在Android上,对于JS交互,往往是通过系统原生提供的@JavascriptInterface这种方式进行交互的,而本人在项目的应该也是使用这种方式。最近听朋友提到一个库——JockeyJS,封装了JS交互逻辑,通过少量的接口让开发者只需要关注Java和JS之间的方法调用。我对它避开@JavascriptInterface的实现比较感兴趣,后来发现JockeyJS有于Java和JS之间的方法调用和回调有着不错的封装,于是便有了分析JockeyJS一文。

一、JockeyJS基本使用

JockeyJS是几年前的库了,虽然是比较久的库,但放到现在仍然可用。

首先,需要在h5页面上引用项目中的jockey.js

接下来在客户端进行配置,JockeyJS主要通过on(String type, JockeyHandler ... handler)和send(String type, WebView toWebView, Object withPayload, JockeyCallback complete)两个方法来实现Java与JS之间的交互。

  • on(String type, JockeyHandler ... handler)这一接口让我们可以在Java上提供给JS需要调用的方法,类似于@JavascriptInterface的功能,type是我们提供的方法名,handler中的回调是我们运行的代码。
jockey.on("useJavaMethod", new JockeyHandler() {
	@Override
	protected void doPerform(Map<Object, Object> payload) {
		// do something
	}
});
  • send(String type, WebView toWebView, Object withPayload, JockeyCallback complete)用于Java调用JS方法,type是调用的方法名,toWebView是调用的webView,withPayload是参数,会转成json传递,complete是调用成功后的回调。
jockey.send("useJsFuntion", webView, null, new JockeyCallback() {
	@Override
	public void call() {
		// secceed to use js function
	}
});

二、JockeyJS原理解析

参考JockeyJS提供的demo,在JockeyJS生效前,需要进行以下设置

jockey = JockeyImpl.getDefault();
jockey.configure(webView);
setJockeyEvents();
  • JockeyImpl.getDefault()这里提供了对Jockey接口的默认实现,也就是对于JS交互这一核心功能的实现。
  • jockey.configure(webView)向JockeyJS传入webView,JockeyJS会对webView进行setJavaScriptEnabled(boolean)和setWebViewClient(WebViewClient)的设置。
  • setJockeyEvents()即一系列的on(String type, JockeyHandler ... handler)操作,添加可供调用的Java方法。

这样的话我们主要关注JockeyImpl.getDefault()的实现。

public static Jockey getDefault() {
	return new DefaultJockeyImpl();
}

可见该方法返回的是DefaultJockeyImpl。跟进DefaultJockeyImpl,发现该类也是继承了JockeyImpl类的,我们先来看DefaultJockeyImpl实现。主要看send(String type, WebView toWebView, Object withPayload, JockeyCallback complete)。

1. Java调用JS的实现
public void send(String type, WebView toWebView, Object withPayload, JockeyCallback complete) {
	int messageId = messageCount;

	if (complete != null) {
		add(messageId, complete);
	}

	if (withPayload != null) {
		withPayload = gson.toJson(withPayload);
	}

	String url = String.format("javascript:Jockey.trigger(\"%s\", %d, %s)",
			type, messageId, withPayload);
	toWebView.loadUrl(url);

	++messageCount;
}

该方法中有一个messageId,这个messageId是做什么用的放在之后再解析。withPayload这个容易理解,是用来传递参数的。接下来,webView进行loadUrl(String url),这个url是send(String type, WebView toWebView, Object withPayload, JockeyCallback complete)方法的关键。url的格式是javascript:Jockey.trigger(\"%s\", %d, %s),即调用了Html的window.Jockey.trigger(type, messageId, json)方法,JS会通过type去匹配相对应的函数并且调用,JS层的具体实现这里不讲。

在和JS交互的业务中,往往需要在调用完JS函数后有一个回调,以便通知我们该函数运行完成,可以继续后续操作。JockeyJS已经集成了这一逻辑。当调用send(String type, WebView toWebView, Object withPayload, JockeyCallback complete)时,会将一个自增的messageId和一个JockeyCallback一一对应保存在_callbacks变量中,Java层将messageId和函数名一起传给JS,JS在运行完相关函数后,会使用该messageId通知Java(通知方式见JS调用Java的实现),Java层的JackeyJS通过messageId找到JockeyCallback并调用来完成回调。这一层逻辑不暴露给开发者,开发者只需要关心JockeyCallback的实现,大大方便了回调的处理。

2. JS调用Java的实现

JS调用Java不通过@JavascriptInterface,那是怎么调用的呢?通过JockeyImpl类可以找到,JockeyJS对webView设置了自己的JockeyWebViewClient,JockeyWebViewClient的特别之处在于重写了shouldOverrideUrlLoading(WebView view, String url)方法。

public boolean shouldOverrideUrlLoading(WebView view, String url) {
	...
	if (isJockeyScheme(uri)) {
		processUri(view, uri);
		return true;
	}
	...
}

这里isJockeyScheme(uri)对url进行了判断:

public boolean isJockeyScheme(URI uri) {
	return uri.getScheme().equals("jockey") && !uri.getQuery().equals("");
}

当url的scheme为jockey时,即url是以jockey://xxx这种格式存在时,JockeyJS会对该url进行拦截,交给应用自己处理,调用processUri(WebView view, URI uri)。

public void processUri(WebView view, URI uri)
		throws HostValidationException {
	String[] parts = uri.getPath().replaceAll("^\\/", "").split("/");
	String host = uri.getHost();

	JockeyWebViewPayload payload = checkPayload(_gson.fromJson(
			uri.getQuery(), JockeyWebViewPayload.class));

	if (parts.length > 0) {
		if (host.equals("event")) {
			getImplementation().triggerEventFromWebView(view, payload);
		} else if (host.equals("callback")) {
			getImplementation().triggerCallbackForMessage(
					Integer.parseInt(parts[0]));
		}
	}
}

JockeyJS从url中取出host和parts,判断host为"event"时,JockeyJS调用getImplementation().triggerEventFromWebView:

protected void triggerEventFromWebView(final WebView webView,
		JockeyWebViewPayload envelope) {
	final int messageId = envelope.id;
	String type = envelope.type;

	if (this.handles(type)) {
		JockeyHandler handler = _listeners.get(type);

		handler.perform(envelope.payload, new OnCompletedListener() {
			@Override
			public void onCompleted() {
				_handler.post(new Runnable() {
					@Override
					public void run() {
						triggerCallbackOnWebView(webView, messageId);
					}
				});
			}
		});
	}
}

JockeyJS通过envelope.type从_listeners拿到对应的JockeyHandler,这些JockeyHandler就是我们初始化JockeyJS时通过on(String type, JockeyHandler ... handler)加入的。接着perform(Map<Object, Object> payload, OnCompletedListener listener)调用doPerform(Map<Object, Object> payload):

protected void doPerform(Map<Object, Object> payload) {
	for (JockeyHandler handler : _handlers)
		handler.perform(payload, this._accumulator);
}

可以看到是对我们注册的JockeyHandler进行调用,这样便实现了JS对Java方法的调用。

单单到这一步还没完成JockeyJS的这一调用流程,接下来成JockeyJS会在doPerform(Map<Object, Object> payload)完成后,通过triggerCallbackOnWebView(webView, messageId)回调JS,通知JS层方法已执行完毕,由JS去执行后续操作。

triggerCallbackOnWebView(webView, messageId)的实现类似于send(String type, WebView toWebView, Object withPayload, JockeyCallback complete),在此就不赘述。

回到host的判断,还有一种host为"callback"的情况,此时JockeyJS会调用getImplementation().triggerCallbackForMessage(int messageId):

protected void triggerCallbackForMessage(int messageId) {
	try {
		JockeyCallback complete = _callbacks.get(messageId, _DEFAULT);
		complete.call();
	} catch (Exception e) {
		e.printStackTrace();
	}
	_callbacks.remove(messageId);
}

很简单,该方法是通知messageId从_callbacks中取出JockeyCallback并调用,即在上文中提到的send(String type, WebView toWebView, Object withPayload, JockeyCallback complete)接收JS回调的实现。

三、总结

JockeyJS无疑是封装良好的用于JS交互的库,不仅仅适用于Android,也兼容iOS平台。通过webView.loadUrl("javascript:xxx")和shouldOverrideUrlLoading(WebView view, String url)方法达到Java和JS的相互调用,并封装了回调逻辑,大大方便业务的开发。当然,随着项目业务需求的增加,JockeyJS还是有可以优化的空间,但是JockeyJS的整体封装值得参考,特别是对于初始项目,可以在JS交互上少走一点弯路。感兴趣的同学也可以继续阅读JockeyJS在JS层和iOS层的代码实现。

JockJs:javascript 库 JOCKJS - An Smart JavaScript Library 简介 此框架吸取了多款主流框架的思想,使用灵活,迷你,核心代码只有2.9K,服务端采用Node架构,实现了对DOM常用的操作方法以及事件、Ajax等封装,拥有模块依赖管理,动态按需载入,在线压缩,模块请求自动合并等。因模块的打包压缩都是在请求的过程中动态完成,所以发布前不需要打包。 配合(css框架)、(组件库)、(业务组件)等组成前端解决方案,拥有丰富的组件库,极大的提升了前端开发效率,完善的性能监控、错误日志监控、事件追踪等支持,为性能、系统稳定性提供了很多保障。目前各个事业部都在使用这套解决方案 线上地址 安装脚本 问题反馈 邮件:<> 立即下载

相关推荐

TwinCAT报SSE invalid operation错误

错误类型 TwinCAT程序中报出以下错误: 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 **** 383 ms | 'Port_851' (851): Exception (Exception Code: 0xc0000090, SSE invalid operation) in PLC Application Untitled1 Instance, Task PlcTask (RBP: 0xffffb3016c80ecc0, RIP: 0xffffe708ee5b5f53, RSP:

akadiao的博客 4162

探索未来交互:JockeyJS 开源库全解析

探索未来交互:JockeyJS 开源库全解析 在跨平台应用开发中,实现原生应用与JavaScript的高效通信是至关重要的。这就是我们引荐JockeyJS的原因,一个专为iOS和Android设计的库,它让两者之间的双向通信变得简单易行。不仅如此,JockeyJS还支持在Webview内的iframe间进行通讯,极大地拓宽了其应用场景。 项目介绍 JockeyJS的核心功能在于提供了一种桥梁,使得...

gitblog_00019的博客 465

MediaPipeUnityPlugin(最新版)摇摆拳人脸识别

MediaPipeUnityPlugin(最新版)摇摆拳人脸识别

不忘初心 方得始终 2982

JockeyJS 开源项目教程

JockeyJS 开源项目教程 1. 项目介绍 JockeyJS 是一个用于在 iOS 和 Android 平台上实现原生应用与 JavaScript 应用之间双向通信的开源库。它不仅支持原生应用与 WebView 中的 JavaScript 应用通信,还支持在 WebView 中运行的 iframe 之间的通信。JockeyJS 通过简单的接口封装了复杂的通信逻辑,使得开发者可以专注于业务逻辑的...

gitblog_00387的博客 1013

11n、11ac、11ax和11be MCS表(全网最全)

1、无线协商速率介绍及计算 2、附11n、11ac、11ax 完整MCS速率表

weixin_41500064的博客 2万+

别再为环保数采仪通讯发愁!手把手教你用MCGS触摸屏+4G模块发送HJ212报文

本文详细介绍了如何使用MCGS触摸屏配合4G模块高效发送HJ212标准报文,解决工业环保监测中的数据采集与传输难题。从硬件连接到软件配置,再到报文组装与发送策略,提供全流程实用指南,特别针对4G网络环境下的特殊设置给出优化建议,帮助工程师提升数据传输稳定性与效率。

weixin_30847865的博客 389

android jockeyjs库对webview的封装

jockeyjs库对h5和native代码交互做了优美的封装。 你可以写出像下面这种风格的代码,本文对它的实现做一个分析。 //Listen for an event from JavaScript and log a message when we have receied it. jockey.on("event-name", new JockeyHandler() { @Ov

yigeid的博客 3449

论文阅读:Visual Relationship Detection with Language Priors

Visual Relationship Detection with Language Priors(ECCV2016) 文章   尽管大多数的relationship并不常见,但是它们的object和predicate却更频繁地独立出现。paper用这个insight分别独立训练训练object和predicate的模型,然后再进行组合来预测relationship。Visual relatio...

Kivee的博客 2877

js动态引入第三方库

文章目录背景解决方案1 目前暂可行的实施方案2 回调函数3 异步加载结束语参考文章 背景 为了方便用户使用sdk,从用户角度想简化引入各种css、js库的麻烦琐事。 问题来了,用document.write可以完美解决这个问题,但问题的问题是虽然浏览器有警告,但它还是执行了,就不知道哪一天会不会直接error出现或者拦截了。 最好的方式当然是采用es6使用import模块的方式,这里是考虑了老的加载方式,即直接通过引入script标签引入js库。 现实情况是难免会有用到引入第三方库的情况。 这里也不考虑使用

既然青春留不住,还是做个大叔好! 6880

Hermes Agent 对阵 OpenClaw:自我改进的 AI 队友

但在 2026 年 2 月,Nous Research 发布了 Hermes Agent,它带来了不同的愿景:一个不仅能够运行,还能学习的代理。在完成复杂的多步骤任务后,它会分析自己的操作并创建一个可复用的技能。对于已在使用 OpenClaw 的澳大利亚企业而言,这意味着您可以试用 Hermes Agent,而无需丢失数月的配置和自定义成果。最重要的区别在于理念:OpenClaw 是一个需要配置的工具,而 Hermes Agent 则是一个会学习的队友。OpenClaw 的技能是静态的。

xiaoshun007的专栏 1571

Android Update Engine 分析(三四)OTA 签名都支持哪些算法?

写了几十篇还没涉及到 OTA 签名算法细节,OTA 讨论群也很少问这个,毕竟签名算法纯理论的问题,一旦实现好就极少需要改动,只需要进行一些配置,准备好签名的秘钥和证书就可以了。限于签名的算法理论太过于抽象,本篇不讨论签名算法细节,但会总结一些签名操作。以及 Android OTA 包支持的签名算法。本文主要分析 Update Engine 中支持的签名算法,以及这些算法的操作实现(不涉及原理部分),并总结签名和验签使用的 key。

洛奇看世界 716

Android js和native交互的两种方法

本博客解决的问题是Android本地方法和webview中js方法交互,方法一是使用的是Android自身js注解,方法二是开源库jockeyjs。方法一:js注解先上js脚本(代码来自网络):<html> <head> <meta http-equiv="Content-Type" content="text/html;charset=gb2312"> <script type="text/

Ethan的博客 5152

Ubuntu18.04安装VCS、Verdi、dve全套教程亲测(有成功截图)

通过下面十个步骤,我们就可以在ubuntu上使用vcs、verdi、dve等软件! 一、安装ubuntu系统,这个不在这里讲了,重点叫安装VCS、Verdi等软件 下面的过程一部分同其他网上流程一致,对其中部分进行修改。如果按照其他网上教程是不会成功的,本人亲测,下面是我试验网上不同文章的流程遇到的错误摸索后总结的流程,按照步骤保证可以成功运行,包括破解流程,使用时间不限制在2020年,可以自定义2030等等。 二、安装文件结构 –synopsys_installer #此程序用于安装下面三个程序。所以你想

QQ_778132974的博客 6364

移动端native和js的交互模式

一,安卓端native和js交互 继承自Activity的界面文件通过重写onCreate()方法设定展示某个含WebView控件的xml布局文件。 ①js调用本地java方法: webview.addJavaScriptInterface(this,”wst”); 首先对webview绑定javaScriptInterface,将Object传递给webview并指定别名,这样j

wolf艺术人生 1826

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

ASP + XML + JavaScript 实现动态无限级联动菜单

  我做某个项目时,有需求的是做一个动态的无限级的联动菜单。由于本人比较懒于是上网找找有关的代码,但很多都没有满足需求,其中有一编文章是用JavaScript对XML文件操作来实现无限级联动菜单的,我们可结合ASP来完成对数据库值的读取,然后写入XML文件,再用JavaScript读出来并且控制它的联动。这儿的关键是把数据库内的N层数据类读出来然后正确写入XML文件中:我的数据库表结构是这样的:

Jockey的专栏 2780

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

xamarin WebView的https 访问实现[备忘]

最近用xamarin 做了个项目,基于Web +APP的混合实现,对于http 访问是可以让android 和 ios 的webview 和WKWebview 直接访问。 到2017年APPLE就强制要求支持https的通讯,因此需要让webview 和 wkwebview 支持https的访问,尤其是自建证书的https。 先试一下直接访问: 1、ios: 直接使用http

Jockey的专栏 2743

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

WebView开源库终极学习方案,如何试出一个Android开发者真正的水平

支持处理js的交互逻辑,方便快捷,并且无耦合,操作十分简单; 暴露进度条加载进度,结束,以及异常状态(分多种状态:无网络,404,onReceivedError,sslError异常等)listener给开发者; 支持视频播放,可以切换成全频播放视频,可旋转屏幕,暴露视频操作监听listener给开发者; 集成了腾讯x5的WebView,最新版本,功能强大; 支持打开文件的操作,比如打开相册,然后选中图片上传,兼容版本(5.0); 支持加载word,xls,ppt,pdf,txt等文件文档,使用方法十分简.

m0_66264699的博客 2252

java webview框架_一网打尽__Android 开源代码合集(WebView框架)

本人会陆续整理收集Android 中不同类列的开源框架。方便开发流程,减少开发查询成本。WebView 框架JsBridgeAndroid的Java和JavaScript桥接地址:https://github.com/lzyzsd/JsBridgeAndroidChromium谷歌浏览器安卓版源码项目地址:https://github.com/JackyAndroid/AndroidChromiu...

weixin_42168830的博客 506

mockjs——mockjs定义、mockjs安装、mockjs使用、mockjs方法、mockjs语法、代码示例

拦截ajax请求,生成伪数据应用场景:在工作中,后端已经出接口文档,还没有实现代码由前端依照接口文档模拟伪数据,实现前端开发功能。

TKY666的博客 2万+

JavaScript||类型转换

数据类型 在 JavaScript 中有 5 种不同的数据类型: string number boolean object function 3 种对象类型: Object Date Array 2 个不包含任何值的数据类型: null undefined typeof 操作符 你可以使用typeof操作符来查看 JavaScript 变量的数据类型。 实例 ty...

JockLiu的博客 225

Hybrid通信原理--Jockey源码解析

1. Hybrid通信原理 1.1 什么是Hybrid通信 本文讲的Hybrid通信指的是:在Hybrid框架中,H5与Native之间的交互。 交互包括两部分: H5访问Native,应用场景有设置导航栏,调用Native组件等; Native访问H5,应用场景有H5分享,执行H5回调等; 1.2 H5与Native交互实现原理 交互分成两中场景: H5访问Native H5发送Schem...

bob_baobao的博客 2236

Android混合编程:WebView实践

关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流。 文章目录 一 基本用法 二 代码交互 三 性能优化 第一次阅览本系列文章,请参见导读,更多文章请参见文章目录。 一 基本用法 WebView也是Android View的一种, 我们通常用...

weixin_33766168的博客 237
上一篇: 关于安桌开发drawable下分置不同分辨率的图片资源
下一篇: 非侵入式无权限应用内悬浮窗的实现
Two212250511
博客等级 码龄14年 1粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值