写点什么

安卓跨平台开发实践

  • 2020-02-12
  • 本文字数:3588 字

    阅读完需:约 12 分钟

安卓跨平台开发实践

AI 大模型超全落地场景&金融应用实践,8 月 16 - 19 日 FCon x AICon 大会联诀来袭、干货翻倍!

移动端目前市面上主流的平台主要有 Android 和 IOS 两大平台,为了尽可能复用代码和节省开发成本,各大巨头都开发了自己的跨平台框架,比如 Facebook 的 React-Native,阿里的 Weex,Cordova,以及今年 Google 开发者大会上介绍的 Flutter 框架。这些框架各有优缺点,但是到目前为止都没有大规模的推广开来,在我看来主要有一下几个原因:


1、开发者生态圈还不够成熟,RN 是三大跨平台框架关注人最多,生态最活跃的框架, 但是到目前为止也没有到 1.0 版本(最新的 release 是 0.57.8),更别说后来者的 Weex 和 Flutter 了。生态不成熟,意味着开发文档少,可以使用的开源控件少,比如在 RN 上想做一个最基本的下拉刷新和上拉加载更多的 listview 都比较费劲。Weex 已经贡献给 Apache,已经很久没有更新 release 了。Flutter 现在还在 beta 版本,其发展还有待观察。


2、性能问题,虽然这几大框架都对渲染性能做了优化,但是相比原生还是差一些,RN 和 weex 都自己实现来了一个浏览器内核(JSCore),因此多了一层 js 解析,渲染会慢一些。比如 RN 的 listview 如果数据量太大就会出现卡顿。Flutter 虽然自带绘制引擎,但是跟原生比起来还是有一些距离。


3、兼容问题,虽然这三大平台的初衷都是为了跨平台(Write/Learn once, run everywhere),但是实际应用中还是需要耗费很多的精力去兼容和适配,比如 RN 在 Android 低端机器上表现就不尽如人意,连曾经 RN 的坚实拥护者 Airbnb 都宣布放弃使用 RN 了。


4、开发集成成本,三个框架都需要学习新的语言 React,vue,dart,weex 的最大优势就是入门简单,但是版本迭代慢,RN 上手门槛高,开发调试难度大,集成 RN 和 weex 框架还会加入很多 so 文件,增加安装包的大小至少在 10M 左右,这还不包括第三方的 library。Flutter 因为刚出来,应用的还不多,其效果还有待观察。


但是移动开发的跨平台是大势所趋,可以节省开发成本,提高开发效率,迅速响应业务变化,现在主流的应用还是使用 H5 和原生的通信来实现跨平台的开发。Android 和 IOS 平台都有自己内置的浏览器内核 webkit 框架,跨平台的本质就是用 H5/JS 编写的代码能够分别运行在 Android 和 IOS 的 WebView 中,从而实现了一套代码两个平台都能运行的目的。


1547108123246047167.png


在 Android 平台上要实现 Native 和 JS 的通信主要通过 WebViewClient 和 WebChromeClient 两个类来实现。WebViewClient 的作用是帮助 WebView 处理各种通知,事件请求,其主要的方法有:onLoadResource,onPageStart,onPageFinished,onReceiveError,shouldOverrideUrlLoading 等方法;WebChromeClient 处理 JS 页面的事件响应,比如网页中的对话框,网页图标,网站标题,网页的加载进度等事件,对应的响应方法有 onJsAlert, onJsConfirm, onJsConsole, onProgressChanged, onReceiveIcon, onReceiveTitle 等。


要实现 Java 和 JS 通信就要:


1,解决 Java 调 JS;


2,JS 调 Java。


Java 调用 JS 通过 loadUrl 和 evaluateJavaScript 两个方法。


通过 webview.loadUrl(“javascript:alert(‘hello world’)”),可以在 android 平台将 js 代码注入到 html 页面,loadUrl 方法可以直接调用 js 中定义的函数,也可以把 android 本地的 assets 目录下的 js 文件以字符串的形式注入到 html 页面中,但是这个注入时机一定要等到 html 页面加载完毕才能做,即在 WebViewClient.onPageFinished 的回调函数中调用,这样就相当于在 html 页面中直接引用了 js 资源文件。对于客户端来说,java 调用 js 本质上是拼接 js 字符串的过程,但是调用 loadUrl 不能直接获取 js 函数的返回值。要实现 Java 调用 js 函数后,可以获取 js 函数的返回值可以使用 webview.evaluateJavaScript 方法,但是该方法只有在 android4.4 及以上的版本才可以使用。其他用法和 loadUrl 一致。


JS 调用 Java 可以分为三种:1,对象映射;2,URL 拦截;3,JS 方法拦截。


对象映射是通过 webview.addJavascriptInterface(new JSObject(), “javaObject”),这样可以 js 代码中可以直接调用 javaObject 对象,从而实现 JS 调用 Java 的功能,但是这个方法在 android4.2 以下会有安全漏洞,利用反射机制调用 Android API getRuntime 执行 shell 命令进行攻击,比如遍历 sdcard,发送短信,安装木马 APK 等。


URL 拦截是指在 html 页面通过 iframe.src,window.open,documention.location 或者 href,这四种方法都可以在 html 页面中打开一个连接,从而会触发 Java 中的 WebViewClient.shouldOverrideUrlLoading 方法。例如在 js 中执行


1547108153585008923.png


在 shouldOverrrideUrlLoading 中可以根据约定的协议格式(Scheme)和协议名(Authority)获取从 JS 中传输过来的数据(Data)。


在 JS 中调用 alert,console,prompt,confirm 等方法就会触发 WebChromeClient 的 onJsAlert,onConsoleMessage,onJsPrompt,onJsConfirm 方法的回调。比如在 js 中可以调用


1547108181168094048.png


在 onJsPrompt 的 message 中可以获取 prompt 的内容,然后根据约定的协议格式可以获取数据。


为了解决 JS 和 Native 的通信问题,需要使用一个 JSBridge 框架(https://github.com/lzyzsd/JsBridge)用来负责H5和Java之间的通信,需要解决的问题:


1、JS 互相 Java 调用后如何回调,将 responseData 传递回去;


2,JS 调用 Java 有三种方法,如果选择哪一种方法比较合适。


针对问题 1,可以在 java 端和 js 端定义一个数据结构: Message={callbackId:xxx, handleName:xxx,responseData:xxx,responseId:xxx}。将回调函数保存在 callbackId 中,当 JS 或者 Java 处理完数据回调的时候再讲保存在 callbackId 的回调函数存放在 responseId,相应的回调的数据存放在 responseData 中,这样就能响应 JS 或者 Java 调用后的回调消息。


Js 调用 Java 的方法虽然有三种,但是 addJavaScriptInterface 存在安全性问题一般不建议使用,JS 中的 alert,console 方法都会在 Html 页面比较常用,confirm 和 prompt 虽然不常用但是某些手机系统版本上会有对话框弹出,不通用,所以比较好的选择是 url 拦截,可以通过 iframe.src 触发 shouldOverrideUrlLoading。


JsBridge 框架的使用主要分为:


1,在 H5 页面加载完毕注入一个本地的 js 文件;


2,Java 代码中注册 BridgeHandler,用来处理 JS 发送过来的消息;


3,在本地注入的 js 文件中定义_handleMessageFromNative,用来接收 java 传递过来的消息;


4,因为客户端注入 js 是异步的,所以需要在 js 文件中注册 Event 监听器,成功后通知 H5。


Native 调用 JS,例如通过


col 1col 2


1


2


3


4 | webview.loadUrl(


"javascript:WebViewJavascriptBridge._handleMessageFromNative('{


\"callbackId\":\"JAVA_CB_2_559\",\"data\":\"just data from java\"


}')");


这样就可以调用 JS 的 handleMessageFromNative 方法,传递的数据格式是 Message,callBackId 响应 js 的回调,发送前会存储到 HashMap 中,js 回调的时候根据 JAVA_CB_2_559 找到对应的的回调函数处理 js 的响应数据,具体流程如下:


1547108235710003647.jpg


Js 调用 Java,通过 sendMessageQueue 将传递的信息转换成


col 1col 2
1Message= {data: {…}, callbackId: ``"cb_1_1234"``}


其中 callbackId 是 js 的回调函数。然后通过


col 1col 2
1iframe.src=’yy:``//return/_fetchQueue/[{"data":"xxxx","callbackId":"cb_1_4321"}]’,


触发 shouldOverrideUrlLoading 方法,java 处理完 js 传递过来的 data 后,将回调函数 cb_1_4321 设置到


col 1col 2
1Message={responseId: cb_1_4321, responseData:XXX},


这样在 js 中就能处理回调函数。具体的流程图如下:


1547108327553011057.jpg


JsBridge 框架提供两种 Handler 方法,registerHandler 方法需要传入 handler 的名字,这样需要 IOS,Android,H5 三方约定这个名字,因为 H5 开发的的业务需求变化比较快,而且 H5 调用原生的方法也是随机的,所以每次都用 registerHandler 约定名字需要使用全局变量存放这些 handler 方法名不便于扩展,所以实际开发中使用 defaultHanlder,H5 调用原生方法的的时候约定一个 cmd,即约定 data={cmd:xxx,time:data:{…}},只要在原生代码中对 cmd 命令有对应的功能,那么 H5 页面就可以随时调用原生的方法。


JSBridge 的改进建议,由于 webview 调用 js 方法的时候必须在主线程才能生效,所以偶然会出现 java 调用 js 失败。另外,Js 调用 Java 偶尔也会失败,因为 iframe 机制不能保证每次都能触发 shouldOverrideUrlLoading 回调。目前 JSBridge 采用的是 url scheme 的方式,如果不考虑 Android4.2 以下,IOS7 以下,可以采用的交互,比如直接使用 addJavaScriptInterface 在 JS 页面注入一个 Native 对象,将之前触发 u 步骤变为使用这个 Native 对象向 Native 发送消息。这种方法只是一个可行的方案,实际使用过程中目前的 JSBridge 方案基本上满足业务需求了。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/211


2020-02-12 15:26578

评论

发布
暂无评论
发现更多内容

从“13天”到“0天”延时,揭秘火山引擎DataLeap SLA保障最佳实践

字节跳动数据平台

大数据 数据治理 数据研发 企业号 3 月 PK 榜

如何通过Java程序加密或者解密PDF文档

Geek_249eec

Java PDF

Mybatis Plus最新代码生成器AutoGenerator,更简单更高效!

Java你猿哥

mybatis ssm Java工程师 java Mybatis-Plus

vivo全球商城:库存系统架构设计与实践

vivo互联网技术

系统架构 电商 库存

镭速传输是如何管理大文件跨国传输的

镭速

DTO、VO、BO、PO、DO的用法区别,居然这么多人搞不清楚.....

程序知音

思码逸任晶磊:ChatGPT 时代的软件研发数据与效能提升

思码逸研发效能

机器学习 研发效能 ChatGPT

基于Mindspore2.0的GPT2预训练模型迁移教程

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 3 月 PK 榜

“鼎新杯”案例精选 | 中国联通数字化研发低代码平台为一线赋能

信通院IOMM数字化转型团队

低代码 数字化转型 中国联通

万字分享:以Code Review 最佳实践,解答降本增效 or 增加成本之问(上)

极狐GitLab

DevOps Code Review 代码安全 代码评审 安全左移

联合解决方案 | 亚信科技AntDB数据库携手浪潮K1 Power赋能关键行业数字化转型,助力新基建

亚信AntDB数据库

数据库 AntDB 国产数据库 AntDB数据库 企业号 3 月 PK 榜

这几个群,程序员可千万不要进!

禅道项目管理

项目管理 程序员 项目管理工具

【实用类】测试使用ChatGPT开发shell脚本 | 社区征文

瀛洲骇客

ChatGPT

MQTT 5.0消息发布流程

EMQ映云科技

物联网 IoT mqtt QoS 企业号 3 月 PK 榜

CleanMyMac4.20汉化免费版Mac清理工具

茶色酒

CleanMyMac4.20

研发效能怎么分析?方法论、模型、误区都在这里了

思码逸研发效能

研发效能

两大国际标准正式发布,百度安全深度参与

百度安全

云图说丨Astro Canvas一站式数据可视化开发,分钟级构建业务大屏

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 3 月 PK 榜

FL Studio21最新版DAW数字音频工作站

茶色酒

FL Studio FL Studio 21

AI脸部美容,一键让你变瘦变美变老变年轻

极客飞兔

php Python AI PaddleGAN 人脸编辑

隔离级别+事务+连接池+锁

hasWhere

【YonBuilder 移动开发】关于创建 App 是否需要 AVM 的经验分享

YonBuilder低代码开发平台

Oracle ASM磁盘组配置、日常运维、故障处理等操作资料汇总

墨天轮

数据库 oracle asm 磁盘管理

数据标注工具,多维度体验优化|ModelWhale 版本更新

ModelWhale

人工智能 标注 标注工具 团队协同 模型管理

柏拉图会反对ChatGPT吗?~深度好文| 社区征文

李韧

人工智能 ChatGPT

基于 Flink 流计算实现的股票交易实时资产应用

Apache Flink

大数据 flink 实时计算

GPU推理服务性能优化之路 | 得物技术

得物技术

Python

捷报频传 | 博睿数据签约华润集团,携手共进共创共赢

博睿数据

可观测性 智能运维 博睿数据 签约 华润集团

web3 NFT代币铸造盲盒抽奖质押dapp游戏系统开发智能合约技术分析

开发微hkkf5566

不用写代码就能开发小程序,浅看产品经理是怎么做到的?

这我可不懂

低代码 低代码平台 JNPF

并发编程详解:从理论基础到案例实战(十三个工具类,十大设计模式)

程序知音

Java 并发编程 设计模式 java架构 后端技术

安卓跨平台开发实践_文化 & 方法_周智_InfoQ精选文章