基于React-Native0.55.4的语音识别项目全栈方案

基于React-Native0.55.4的语音识别项目全栈方案

【摘要】 移动端的API能力验证方案与PC端不一样!不一样!!不一样!!! 即使需要使用的API都存在,也不一定能用,这一点和PC端是有很大区别的,国内的手机系统虽然都是基于Android,但几乎都会经过各大厂商的定制,功能与原版Android系统并不是完全一致的,在考察技术方案的时候一定要确认用demo把功能跑起来才可以,别问我怎么知道的。

一. 移动端直接访问Web应用?
PC端基于 Web API 的语音识别方案可参考 《【Recorder.js+百度语音识别】全栈方案技术细节》 一文。
1. 调用 Web API 的多媒体采集接口需要特定的域
Web API 的多媒体接口是 WebRTC 技术在PC端的实现,由于多媒体采集涉及到用户隐私,所以在浏览器端调用这个接口需要在安全的域下才能被调起,安全的域是指以下三类:

  • file:/// 本地域
  • http://localhost 本地web服务器
  • https:// 安全域

前两类一般用于桌面应用和本地调试,实际网站上线部署需要以 https 方式部署,如何部署 https 及申请免费的CA证书等网上有很多文章讲解,本文不再赘述。
2. 手机浏览器几乎都不直接支持 WebRTC 接口
将PC端的Web应用以 https 方式部署好之后,从手机浏览器直接访问时无法唤起录音接口权限认证, navigator.getUserMedia( ) 方法一只返回 permissionDenied 错误,无论是在 Android6.0 以下通过编辑 manifest.xml 添加还是 Android6.0 以上通过动态获取的方式取得 RECORD_AUDIO 权限,网站都可以正常访问,相关的 Web API 接口也都存在,但即使获得用户授权后也无法调起录音功能。笔者测试了 UC浏览器 百度移动浏览器 Android6.0(API23)自带的浏览器 Android8.0(API26)自带的浏览器 ,结果是都不支持。
二. 方案调研和新的坑
o( ̄▽ ̄)d 既然从移动端直接访问Web应用时无法调起录音接口,至少是无法兼容很多系统和机型,如果不考虑直接原生开发Android的话,只有寄希望于Hybrid的方案了。
2.1 WebView

  • 方案
    在一个app中单页面全屏放置一个WebView组件,然后加载https方式部署的web应用。
  • 理由
    手机浏览器无法支持的情况下,只能寄希望于 WebView WebView 是Android底层用于加载网页的组件,Android4.4版本以后已将内置的浏览器引擎更换为chromium,也就是chrome的内核,从 Can I Use 上查询的支持度是Android5.0以上的版本的 WebView 都是支持 WebRTC 接口的 getUserMedia( ) 方法的。
  • 测试结果
    应用编译目标版本为 API23 ,在支持 API23 (Android6.0)的虚拟机和真机中测试,均无法通过 WebAPI 接口调起麦克风进行录音。在支持 API26 (Android8.0)版本的虚拟机中,功能均可实现。最终在 Can I Use 中对于 getUserMedia( ) 方法支持度的统计信息的备注中,发现已知问题中在写明了:


简单地说就是这个方法在 Android webview iOS PWA 基本都用不了。建议以后开发中可能用到一些不常用的API时完整地看一下相关信息。

  • 结论:
    Android8.0支持,Android支持度不佳,不建议使用。

2.2 crosswalk


  • 方案
    官方网址: crosswalk-project.org/
    利用 crosswalk ,在进行app打包时,将 webview 内核替换为 xwalk (crosswalk开发的基于chromium的浏览器内核),以扩展原生 webview 的能力。
  • 理由
    既然原生 webview 功能被阉割,那么可以利用这个小型黑科技来把一个功能更强大的浏览器内核跟自己的应用打包在一起,笔者3年前在 cordova 2.0-3.0版本流行的年代使用过这个技术,好处是的确可以扩展 webview 的能力无疑,不好的地方在于app项目会直接增大80-90Mb的体积,当然通过几个版本的迭代,现在crosswalk可以针对手机内核类型生成不同的包,app体积增量大约在20Mb,基本属于可接受范围。
  • 测试结果
    遗憾地是这个项目一年前已经停止维护了,最后一版的官方脚手架工具也无法初始化新的工程,间接使用的方式分为两种,第一,下载 crosswalk 的包,手动在 android 工程中替换原生 WebView ,对Hybrid开发者来说难度较大且与hybrid技术兼容性不可控;另一种方案在下一小节说明。
  • 结论:
    不建议使用,有那个精力真不如去研究一下可靠的hybrid方案。

2.3 Cordova/ionic


  • 方案
    官方网址: https://cordova.apache.org
    codova 是一个很流行的hybrid方案,现在已经升级到8.0.0版本,它本身就是一个将web应用打包为app的解决方案。 cordova 的基本原理是将一般 UI 层操作和功能放在 WebView 里实现,需要调用移动设备硬件或原生接口时,均通过添加 cordova 插件的形式来实现,每一个 cordova 版本都会横跨支持若干个 Android 版本,例如新的 cordova7.0.0 在官方文档的说明中是支持android从4.4到8.1版本的,笔者认为非常适合小型hybrid开发团队使用。
  • 理由
    值得一提的是 cordova 拥有一个非常流行的移动端开发××× ionic ,现在已经迭代至 4.0 阶段,这个技术笔者是有特殊感情的,当年 ionic 还在 alpha 版本的时候,笔者就在使用了,它是基于 cordova+angular 这个技术组合的,拥有清新且设计感极强的UI组件,非常值得尝试。另外, cordova 是拥有 crosswalk 插件的,可以直接以插件的形式,在 cordova 项目打包时加入 crosswalk ,有相关需求的读者可以以一试,尤其是团队里没有Android开发人员也没有专门的设计人员的时候, ionic 出品的应用一定会让别人对你另眼相看。
  • 测试结果
    笔者曾在使用 cordova 3.3的时候就融入过 crosswalk ,也通过 cordova 插件成功调用过底层的 GPS 摄像头 及其他一些原生组件,当时是为了适配Android4.4版本。 cordova7.0.0 的脚手架经测试在国内是可以使用的,新建的工程无论是通过自带命令行还是import进Android Studio来进行开发都可以打包为对应的工程,官方文档有很详细的调用各种底层接口的说明,网上也有 cordova7.0.0+crosswalk 方案对应的技术贴。
    笔者由于技术协议中指定技术栈的缘故,无法中途替换解决方案,故本次未进行测试。
  • 结论:
    可考虑作为整体解决方案进行尝试。

2.4 React-Native


  • 方案
    官方网址: https://reactnative.cn
    这是笔者本次使用的方案,由于web端采用 React 技术栈完成的缘故,为了不增加团队小伙伴的学习成本,移动端就选用了 React-Native 的方案。这个方案既可以按照混合开发的方式来进行,也可以按照单个 WebView 的方式来进行(已验证这种方案无法支持 WebRTC )。
    可能很多人已经听说去年 Airbnb 公开宣布不再继续使用 React-Native 作为移动端解决方案并做了详细的解释,当时也是很多人鼓吹说 React-Native 要凉凉了。实际上 Airbnb 在声明中说的很清楚, React-Native 是非常好的hybrid解决方案,他们所遇到的问题是当性能和用户体验优化到一定程度时,在hybrid技术的维护和开发上投入的人力过多了,整个项目的前端人员不仅有Web前端,还有高级的 Android IOS 人员来保障hybrid项目的推进,他们认为这样的人力成本相比于原生开发而言要高很多,所以更换了方案。听明白了吗?所以作为软件技术比国外落后不知道多少年的天朝码农,考虑实际的项目需求,尽管放心大胆地用就好了,跟风真的没什么价值。
  • 理由
    热门的hybrid解决方案,和Web前端三驾马车之一的 React 属同门,语法和组件结构相似度高,社区活跃且周边生态较好。
  • 测试结果
    React-native 已经发布 0.57.3 版本,但经测试 0.55.4 在国内属于可正常新建工程的版本(使用 react-native init XXX 命令创建的工程), 0.56 大版本中发布的两个小版本均在初始打包时报错,命令行的提示链接到一个已知issue,但可惜照做以后也未能打包成功, 0.57 默认的Android-SDK是 API27 ,也就是Android8.1,对于经验不足的开发者来说(比如我自己),太新的版本也不建议使用,除非你的项目是在指定机器上运行的。
    React-native 也封装了 WebView 组件,但很遗憾,直接加载web应用的方式经测试也无法调起 getUserMedia( ) 这个方法,所以 最终只能通过混合开发的方案来实现 (但回过头来想,跟通过 WebView 来调用硬件接口相比,其实这种实现方式反而更符合逻辑)。
  • 结论:
    建议未掌握多语言混合开发能力的hybrid开发者尽可能选用热门方案,理由很简单,所有的前端项目都有坑,但热门项目出了问题可以找大牛咨询。

WebRTC 技术录音相关的 navigator.getUserMedia , navigator.mediaDevices.getUserMedia , AudioContext 这上面这几个方案中都是存在的,但事实是都没能在 webview 中调起麦克风进行录音。
当然 WebRTC 作为独立的标准和技术,也是可以融入Android工程的,但从前端开发者的角度来说这条路就有点跑偏了,执着于 WebRTC 或者团队里有原生开发者的小伙伴可以研究一下。
三. React-Native方案的整体架构


基本上只要多复用现成的组件,加上适量的定制,尽可能不使用一些奇技淫巧,产品的流畅度基本区分不出来是否是Hybrid开发还是Native开发,当然跟笔者的项目体量不是很大也有一定关系。
四. 使用插件清单

五. RN开发细节和遇到的坑

  1. 真机调试时,需要摇晃手机,在配置菜单中填写 内网IP+端口号 ,否则会直接红屏报错。
  2. 真机调试时,需要在设置中开启应用的 悬浮框 权限,否则可能白屏什么都不显示。
  3. WebRTC Android WebView 兼容性不好, IOS 内置浏览器不支持。
  4. react-native-audio 进行录音时,每一次调用 Stop 之后,若要再次启动录音功能,必须先调用 AudioRecorder.prepareRecordingAtPath( ) 方法重新初始化,否则会红屏报错。
  5. WebView 组件必须设置 ref={(webview)=>{this.webview = webview}} ,否则 onMessage 属性无法监听到来自 WebView 加载网页通过 window.postMessage 发来的消息。
  6. TouchableHighlight 组件必须先设置 onPress 属性的回调函数(可以为空函数),否则触摸变色的响应属性 UnderlayColor 无法生效。
  7. Modal 组件在一个自定义组件中只能有一个(如果有多个必须通过条件判断只实例化一个),否则即使未显示的 Modal 组件的 Visible 属性设置为 false ,其实例方法也会和另一个 Modal 组件发生重叠覆盖,可能出现的现象就是显示了第一个 Modal 的界面,却执行了第二个 Modal 的同名方法。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至: huaweicloud.bbs@huawei.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

发布于 2019-10-30 16:28

文章被以下专栏收录