H5必知必会之与App交互

更新日期: 2019-04-10阅读: 3929标签: 交互
来自:奇舞周刊,作者:李松峰 ,资深技术图书译者,翻译出版过40余部技术及交互设计专著,现任360奇舞团高级前端开发工程师,360前端技术委员会委员、W3C AC代表 2018年11月26日发表的“360 AI音箱H5开发实践”一文中,曾简单提到“与Native交互”。

本文将就此主题深入探讨H5与App交互的几种常见模式。 首先声明,本文涉及的H5与App交互协议和模式没有什么特别独到之处,相反,它们恰恰是在业界既有经验基础上结合项目实际归纳提炼出来的。因此,文中涉及的技术和代码可以看作是行业经验落地的产物,不涉秘,也不是权威做法,仅供业界同仁参考。


1. 概述

H5,在中国被专门用来指代开发内嵌于手机应用中的网页的技术,外国好像并没有这个说法。从技术上讲,H5是html5即Hyper Text Markup Language(超文本标记语言)第5版的简称。而HTML只是开发网页要用到的多种技术之一。除了HTML,还要用css设计界面,用JavaScript实现交互,甚至要用Node.js实现服务端逻辑。为什么H5会被用来笼统地指代这些技术呢?我猜一是因为它简单,二是移动端网页开发技术又恰好需要这么一个概念。

移动端网页运行在手机应用内嵌的浏览器引擎中,这个没有UI的内核容器统称WebView,即iPhone的UIWebView(iOS 2.0–12.0)、WKWebView(iOS 8.0+,macOS 10.10+)和Android的WebView。总之,WebView就是在手机应用中运行和展示网页的界面和接口(神奇的是,英文Interface,既可以翻译成“界面”也可以翻译成“接口”)。

H5与原生应用的交互都是通过原生应用中的WebView实现的。通过这个环境,H5可以调用原生应用注入其中的原生对象的方法,原生应用也可以调用H5暴露在这个环境中的JavaScript对象的方法,从而实现指令与数据的传输。

比如,在Android应用中,WebView类有一个公有方法addJavascriptInterface,签名为:

public void addJavascriptInterface (Object object, String name)

调用这个方法可以向WebView中以指定的名称name注入指定的Java对象object。这样,WebView中的JavaScript就可以通过name调用object的方法。比如:

class JsObject {
 @JavascriptInterface
 public String toString() { return "injectedObject"; }
}
webview.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");

在iOS或macOS中,需要通过创建WKWebView类的实例在应用中嵌入网页,交互过程类似。


2. 基础接口

所谓基础接口,就是首先要规定原生应用和JS分别在WebView里注入/暴露一个什么对象:

  • NativeBridge:原生应用注入到WebView中的对象

  • JSBridge:JS暴露在WebView中的对象

并约定在这两个对象上分别可以调用什么方法:

  • NativeBridge.callNative(action, params, whoCare)

  • JSBridge.callJS(action, params, whoAmI)

顾名思义,NativeBridge.callNative是由JS调用向Native传递指令或数据的方法,而JSBridge.callJS则是由Native调用向JS传递指令或数据的方法。方法签名中的参数含义如下:

  •  action:字符串,希望Native/JS执行的操作

  •  params:JSON对象,要传给Native/JS的数据

  •  whoCare:数值,表示JS希望哪个端响应

  • whoAmI:数值,表示哪个端调用的JS

基础接口只有两个对象和两个方法,JS与App间的互操作则通过action和params来扩展和定义。


3. 实现模式

对于JS而言,虽然这里只定义了一个对象一个方法,但实践中,可以把action对应方法的实现附加到JSBridge上,只要把callJS实现为一个分发方法即可,比如:

window.JSBridge = {}
window.JSBridge.callJS = function({action, params, whoAmI}) {
   return window.JSBridge[action](params, whoAmI)
}

这样,所有对callJS的调用,都会转化成对JSBridge上相应action方法的调用,优点是只需一行代码。

另一种实现方式是通过switch...case语句实现调用分发,比如:

function callJS(action, params, whoAmI) {
	params = JSON.parse(JSON.stringify(params))
	switch(action) {
		case 'showSkill':
			const category = params.category
			JSBridge.showSkill(category)
			break
		case 'showSkillDetail':
			const id = params.id
			JSBridge.showSkillDetail(id)
			break
		case 'otherAction':
			// some code
			break
		default:
	}
}
// JS暴露给应用的通用接口
const SpkJSBridge = {}
// 全部接口
JSBridge.callJS = callJS

这样实现的优点是所有方法一目了然,当然同样也是把所有相关接口都附加到同一个JSBridge对象上。

以上两种实现模式各有利弊。


4. 单向调用

由JS发起的单向调用App的操作,主要涉及加载URL和切换到原生界面,可对应如下action:

  • loadUrl:加载另一个URL

  • loadContent:跳转到原生界面

loadUrl调用的参考协议如下:

NativeBridge.callNative({
 action: 'loadUrl',
 params: { url },
 whoCare: 0
})

这里NativeBridge是App的原生对象,其callNative方法被调用时,会收到一个对象(字典/映射)参数。根据这个参数的action属性的值,App可知需要执行的操作是加载URL。于是再取得params属性中的url,发送请求即可。

loadContent调用的参考协议如下:

NativeBridge.callNative({
	action: "loadContent",
	params: {
		type: "album",
		content: {
			album_id: "1"
		}
	},
	whoCare: 0
})

同上,这里通过params向App传递了必要参数,App负责切换到相应的原生界面。

由App发起的单向调用JS的操作,主要涉及用户点击后退按钮(<),可对应如下action:

  • can_back:询问JS是否返回前是否需要用户确认

can_back调用的参考协议如下:

JSBridge.callJS({
 action: "can_back",
 params: {},
 whoAmI: 1/2
})

此调用返回的值示例如下:

{
 can: true,
 target: "prev"
}

顾名思义,can_back用于App询问JS:在返回上一级界面前,是否弹窗提示用户?

返回值中的can如果是true,则直接返回,不提示;如果是false,则弹出一个确认框,请用户确认。另一个值target是与App约定的返回目标,比如prev表示返回上一级,top表示返回顶级,等等。


5. 双向调用

双向调用是JS先调用App,然后App在完成操作后再调用JS,双向通常都需要传递数据。双向调用主要涉及JS调用App原生组件和用户点击右上角按钮,可对应如下action:

  • loadComponent:调用原生组件

  • displayNextButton:显示“下一步”“保存”或“完成”按钮

loadComponent的参考协议如下:

NativeBridge.callNative({
	action: 'loadComponent',
	params: {
		type: 'location',
		value,
		callbackName: 'set_location'
	},
	whoCare: 0
})

在这个例子中,涉及JS调用App显示其实现的城市选择组件:type: 'location',用户选择完城市之后,App再调用set_location,将用户选择的城市名称传给JS:

JSBridge.callJS({
	action: 'set_location',
	params: {
		value: '北京市朝阳区',
	},
	whoAmI: 1 / 2
})

JS根据拿到的值更新界面,完成一次双向调用。另一个例子是JS调用原生的日期选择组件,与此类似。

为什么叫displayNextButton?因为根据具体业务场景,可能存在如下三种情况:

  1. 当前WebView不需要显示右上角按钮,比如详情页;

  2. 当前WebView需要显示“下一步”或“保存”按钮,但需要禁用变灰;

  3. 当前WebView需要显示“下一步”或“保存”按钮,允许用户点击。

displayNextButton协议的参考实现如下:

NativeBridge.callNative({
	action: "displayNextButton",
	params: {
		name: "下一步",
		enable: false,
		callbackName: "save_form"
	},
	whoCare: 0
})

以上代码示例表明,JS调用App,告诉App显示“下一步”按钮,但是要禁用变灰,因为enable: false。如果传递的是enable: true,那么用户就可以点击“下一步”按钮了。点击之后,App再调用JS的save_form。最后,如果不想显示按钮,可以传递name: ''。

下面重点说一下用户点击“下一步”按钮,App调用save_form的场景。此时也分两种情况:

  1. JS直接保存数据

  2. JS通过App保存数据

如果是JS通过App保存数据——可能因为App端实现了数据写入必需的加密机制——那么,JS可以在App调用save_form时将约定好的数据返回给App,由App去保存数据。

如果是JS直接保存数据,比如通过Ajax,那么在保存完数据之后,则还需要调用前面所说的App暴露的loadUrl或loadComponent方法,以告知App切换界面。当然这种情况下会出现第三次调用,但仍然属于双向调用。


6. 哪方主导

本文介绍了JS与App交互的几种模式,而且只讨论了JS端的实现。在开发实践中,团队各端总会面临哪一端主导的问题。本文展示的参考实现就是H5端主导的一种实现形式。H5主导的特点是把主要业务逻辑都封装到WebView中,App主要协同配合,而优点是业务逻辑的变更不会蔓延到App。毕竟相对于H5,App的安装部署模式会造成多版本共存问题,需要尽可能控制新版本。假如由App端主导,将逻辑封装在App端,势必造成版本不受控,给整个项目或产品埋下隐患。

当然,事无绝对。具体情况还要具体分析。而且,哪方主导有时候也取决多方面因素。实践中还是要因人、因时、因势制宜。


来自:奇舞周刊 

 

链接: https://www.fly63.com/article/detial/2824

RN混合开发,React Native与原生android和ios的交互通信

React-Native新版本(从原生发送消息到JS),Android/iOS原生模块给ReactNative发送事件,通知监听,通过DeviceEventEmitter,NativeEventEmitter通过原生应用通讯。

H5页面基于接口实现数据交互

对于现在APP开发来说,目前流行的两个方式是原生和H5。就如同之前业界程序猿争论的BS和CS之争一样,业界对于H5和原生也有不小的争论。对于前者的争论在于PC端,后者在于移动端上体现。

设计师们做UI设计和交互设计、界面设计等一般会去什么网站呢?

明明可靠颜值吃饭,却偏偏要靠才华立身,UI设计师就是这样一群神奇的物种。面对“大的同时小一点”、“五彩斑斓黑”、“下班之前给我”……这些甲方大大刁钻的需求,设计师每天都在咬牙微笑讨生活。

网站交互、开发方式和前端框架介绍

这个世界唯一不变的可能就是变化,历史的车轮滚滚向前,它不会因任何人的消极缓慢而停止。时代抛弃你时,连一声再见都不会说。从最开始的Javascrpit、到后来的Jquery、(ExtJs、EasyUI、MiniUI)、Bootstrap、Layui

three.js 事件交互

在three.js中,展示的一切内容都是在canvas中绘制的,所以点击事件点击到物体上是无法获取点击对象的,要获取点击的对象要使用RayCaster,用于在三维空间中进行鼠标拾取

前后端交互技术有哪些

我们都知道,一个完整的IT项目是由多个不同岗位的成员共同完成,包含UI规划、前端开发、后端开发、测验等。为了完成项目的完整性,前后端需求运用技能完成联通。不过,前后端交互技能有哪些呢?

CSS 状态管理,玩出花样了!

CSS用于交互的方式无非就那么几种:伪类::hover、:link、:active ...动画:animation过渡动画:transition,这些交互方式组合起来,真的可以玩出一些花样,例如我们本文的主题,CSS的状态管理

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!