Skip to content

Commit

Permalink
修改文档
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangyuecn committed Aug 23, 2019
1 parent 98db14d commit c87f82f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 15 deletions.
6 changes: 3 additions & 3 deletions app-support-sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

## 【IOS】Hybrid App测试

[demo_ios](https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_ios)目录内包含IOS App测试源码,和核心文件 [RecordAppJsBridge.swift](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/demo_ios/recorder/RecordAppJsBridge.swift) ;clone后用`xcode`打开后编译运行(没有Mac OS? [装个黑苹果](https://www.jianshu.com/p/cbde4ec9f742) )。本demo为swift代码,兼容IOS 9.0+。
[demo_ios](https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_ios)目录内包含IOS App测试源码,和核心文件 [RecordAppJsBridge.swift](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/demo_ios/recorder/RecordAppJsBridge.swift) ;clone后用`xcode`打开后编译运行(没有Mac OS? [装个黑苹果](https://www.jianshu.com/p/cbde4ec9f742) )。本demo为swift代码,兼容IOS 9.0+,已测试IOS 12.3


## 【Android】Hybrid App测试

[demo_android](https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_android)目录内包含Android App测试源码,和核心文件 [RecordAppJsBridge.java](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/demo_android/app/src/main/java/com/github/xianyuecn/recorder/RecordAppJsBridge.java) ;目录内 [app-debug.apk.zip](https://xiangyuecn.github.io/Recorder/app-support-sample/demo_android/app-debug.apk.zip) 为打包好的debug包(40kb,删掉.zip后缀),或者clone后自行用`Android Studio`编译打包。本demo为java代码,兼容API Level 15+。
[demo_android](https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_android)目录内包含Android App测试源码,和核心文件 [RecordAppJsBridge.java](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/demo_android/app/src/main/java/com/github/xianyuecn/recorder/RecordAppJsBridge.java) ;目录内 [app-debug.apk.zip](https://xiangyuecn.github.io/Recorder/app-support-sample/demo_android/app-debug.apk.zip) 为打包好的debug包(40kb,删掉.zip后缀),或者clone后自行用`Android Studio`编译打包。本demo为java代码,兼容API Level 15+,已测试Android 9.0

## 【IOS微信】H5测试
[<img src="../assets/demo-recordapp.png" width="100px">](https://jiebian.life/web/h5/github/recordapp.aspx) https://jiebian.life/web/h5/github/recordapp.aspx
Expand Down Expand Up @@ -73,7 +73,7 @@ IOS其他浏览器||
- `IOS-Weixin`不支持实时回调,因此当在IOS微信上录音时,实时音量反馈、实时波形等功能不会有效果;并且微信素材下载接口下载的amr音频音质勉强能听(总比没有好,自行实现时也许可以使用它的高清接口,不过需要服务器端转码)。
- `IOS-Weixin`使用的`微信JsSDK`单次调用录音最长为60秒,底层已屏蔽了这个限制,超时后会立即重启接续录音,因此当在IOS微信上录音时,超过60秒还未停止,将重启录音,中间可能会导致短暂的停顿感觉。
- `demo_ios`中swift代码使用的`AVAudioRecorder`来录音,由于录音数据是通过这个对象写入文件来获取的,可能是因为存在文件写入缓存的原因,数据并非实时的flush到文件的,因此实时发送给js的数据存在300ms左右的滞后;`AudioQueue``AudioUnit`之类的更强大的工具文章又少,代码又多,本质上是因为不会用,所以就成这样了。
- `Android WebView`本身是支持录音的(古董版本就算啦),仅需处理网页授权即可,但Android里面使用网页的录音权限问题可能比原生的权限机制要复杂,为了简化js端的复杂性(出问题了好甩锅),不管是Android还是IOS都实现一下可能会简单很多因此就有了Android版的Hybrid App Demo。
- `Android WebView`本身是支持录音的(古董版本就算啦),仅需处理网页授权即可,但Android里面使用网页的录音权限问题可能比原生的权限机制要复杂,为了简化js端的复杂性(出问题了好甩锅),不管是Android还是IOS都实现一下可能会简单很多;另外Android和IOS的音频编码并非易事,且不易更新,使用js编码引擎大大简化App的逻辑;因此就有了Android版的Hybrid App Demo。


# :open_book:快速使用
Expand Down
42 changes: 41 additions & 1 deletion app-support-sample/demo_android/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,41 @@
待编写
[Recorder](https://github.com/xiangyuecn/Recorder/) | [RecordApp](https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample)

# :open_book:Android Hybrid App

目录内包含Android App测试源码,和核心文件 [RecordAppJsBridge.java](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/demo_android/app/src/main/java/com/github/xianyuecn/recorder/RecordAppJsBridge.java) ;目录内 [app-debug.apk.zip](https://xiangyuecn.github.io/Recorder/app-support-sample/demo_android/app-debug.apk.zip) 为打包好的debug包(40kb,删掉.zip后缀),或者clone后自行用`Android Studio`编译打包。本demo为java代码,兼容API Level 15+,已测试Android 9.0。

本Demo是对[/app-support-sample/native-config.js](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/native-config.js)配置示例中定义的JsBridge接口的实现。

可以直接copy目录内`RecordAppJsBridge.java`使用,此文件为核心文件,其他文件都是没什么价值的;支持新开发WebView界面,或对已有的WebView实例升级支持RecordApp。


## 【截图】
![](../../assets/use_native_android.gif")


## 【限制】

- 虽然兼容API Level 15+,但实际上17+才是好的选择,因为addJavascriptInterface
- 古董WebView(21-)虽然能正常接收PCM和进行MP3、WAV编码,但对Blob对象的播放不一定能良好支持



# :open_book:原理

通过addJavascriptInterface往WebView注入一个全局对象`RecordAppJsBridge`,js中通过`window.RecordAppJsBridge`来访问,只有存在这个对象,就代表是在App中;js通过这个对象的`request`方法和java进行数据的交互。


## 数据交互
java收到js发起的`RecordAppJsBridge.request`请求,解析请求数据参数,并调用参数中接口对应的java方法,同步执行完后把数据返回给js,如果方法是异步的,将在异步操作完成后java将调用网页的js方法`AppJsBridgeRequest.Call`将数据异步返回。


## 录音接口
接口对应的方法使用的`AudioRecord`来录音,`AudioRecord`使用稳健的44100采样率进行音频采集,我们实时接收PCM数据并进行采样率的转换,然后调用`AppJsBridgeRequest.Record`把数据返回给js端即可完成完整的录音功能。

Android端的录音还算完美,比IOS的轻松很多。


## 为什么不用UserAgent来识别App环境

通过修改WebView的UA来让H5、服务器判断是不是在App里面运行的,此方法非常简单而且实用。但有一个致命缺陷,当UA数据很敏感的场景下,虽然方便了我方H5、服务器来识别这个App,但也同时也暴露给了任何在此WebView中发起的请求,不可避免的会将我们的标识信息随请求而发送给第三方(虽然可通过额外编程把信息抹掉,但代价太大了)。IOS不动UA基本上别人的服务器几乎不太可能识别出我们的App,Android神一样的把包名添加到了X-Requested-With请求头中,还能不能讲理了。

44 changes: 42 additions & 2 deletions app-support-sample/demo_ios/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,42 @@
待编写
123
[Recorder](https://github.com/xiangyuecn/Recorder/) | [RecordApp](https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample)

# :open_book:IOS Hybrid App

本目录内包含IOS App测试源码,和核心文件 [RecordAppJsBridge.swift](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/demo_ios/recorder/RecordAppJsBridge.swift) ;clone后用`xcode`打开后编译运行(没有Mac OS? [装个黑苹果](https://www.jianshu.com/p/cbde4ec9f742) )。本demo为swift代码,兼容IOS 9.0+,已测试IOS 12.3。

本Demo是对[/app-support-sample/native-config.js](https://github.com/xiangyuecn/Recorder/blob/master/app-support-sample/native-config.js)配置示例中定义的JsBridge接口的实现。

可以直接copy目录内`RecordAppJsBridge.swift`使用,此文件为核心文件,其他文件都是没什么价值的;支持新开发WKWebView界面,或对已有的WKWebView实例升级支持RecordApp。


## 【截图】
![](../../assets/use_native_ios.gif)


## 【限制】

- 未做古董版本UIWebView适配,理论上并不需要太大改动就能支持,并不打算进行支持
- 未测试在OC中调用此swift文件,并不打算去写OC代码(学不动)




# :open_book:原理

通过userContentController往WKWebView注入一个全局对象`RecordAppJsBridgeIsSet`,js中通过`webkit.messageHandlers.RecordAppJsBridgeIsSet`来访问,只有存在这个对象,就代表是在App中;但并不通过这个对象来进行数据交互,因为它仅支持异步操作;数据交互需要一个同步方法来进行支持,因为同步可以实现异步,仅支持异步的只能异步到底,所以选择重写WebView的prompt弹框方法,进行数据的交互。


## 数据交互
swift收到js发起的prompt弹框请求,解析弹框携带的数据参数,并调用参数中接口对应的swift方法,同步执行完后把数据返回给prompt弹框,如果方法是异步的,将在异步操作完成后swift将调用网页的js方法`AppJsBridgeRequest.Call`将数据异步返回。


## 录音接口
接口对应的方法使用的`AVAudioRecorder`来录音,`AVAudioRecorder`会把录音PCM数据写入到文件,因此我们实时从这个文件中读取出数据,然后定时调用`AppJsBridgeRequest.Record`把数据返回给js端即可完成完整的录音功能。

可能是因为`AVAudioRecorder`存在文件写入缓存的原因,数据并非实时的flush到文件的,因此实时发送给js的数据存在300ms左右的滞后;`AudioQueue``AudioUnit`之类的更强大的工具文章又少,代码又多,本质上是因为不会用,所以就成这样了。


## 为什么不用UserAgent来识别App环境

通过修改WebView的UA来让H5、服务器判断是不是在App里面运行的,此方法非常简单而且实用。但有一个致命缺陷,当UA数据很敏感的场景下,虽然方便了我方H5、服务器来识别这个App,但也同时也暴露给了任何在此WebView中发起的请求,不可避免的会将我们的标识信息随请求而发送给第三方(虽然可通过额外编程把信息抹掉,但代价太大了)。IOS不动UA基本上别人的服务器几乎不太可能识别出我们的App,Android神一样的把包名添加到了X-Requested-With请求头中,还能不能讲理了。

19 changes: 14 additions & 5 deletions app-support-sample/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,18 @@
}
</style>
<a class="navItem" href="https://xiangyuecn.github.io/Recorder/">
<div class="navTitle">Recorder测试</div>
<div class="navDesc">Recorder库使用简单,功能丰富,支持PC、Android,但IOS上仅Safari支持录音</div>
<div class="navTitle">Recorder H5</div>
<div class="navDesc">Recorder H5使用简单,功能丰富,支持PC、Android,但IOS上仅Safari支持录音</div>
</a>

<a class="navItem slc" href="https://jiebian.life/web/h5/github/recordapp.aspx">
<div class="navTitle">RecordApp测试</div>
<div class="navTitle">RecordApp</div>
<div class="navDesc">RecordApp除Recorder支持的外,支持Hybrid App,IOS上支持微信网页和小程序web-view</div>
</a>
</div>



<!-- begin 开始copy源码 -->
<div>
<div class="pd">
<span style="font-size:18px;color:#ef6ea8">似乎仅为仅为兼容IOS而生</span>
Expand Down Expand Up @@ -199,6 +198,15 @@
<hr>
<audio class="recPlay" style="width:100%"></audio>
<div class="reclog"></div>

<hr>
<div class="pd">
【测试App】
IOS Demo App:<a href="https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_ios">下载源码</a> 自行编译

,Android Demo App:<a href="https://xiangyuecn.github.io/Recorder/app-support-sample/demo_android/app-debug.apk.zip" download="app-debug.apk">下载APK</a> (40kb,删除.zip后缀,<a href="https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_android">源码</a>)
</div>

<div class="recinfo"></div>
</div>
<script type="text/template" class="tp_recinfo">
Expand Down Expand Up @@ -612,7 +620,6 @@ <h3>ConsoleX:</h3>
</script>
</div>
<div style="padding:100px;"></div>
<!-- end 结束copy源码 -->



Expand Down Expand Up @@ -684,6 +691,8 @@ <h3>ConsoleX:</h3>
}else{
reclog("此页面由服务器代理,源网址<a href='https://xiangyuecn.github.io/Recorder/app-support-sample/'>https://xiangyuecn.github.io/Recorder/app-support-sample/</a>");
};

reclog("<span style='color:#0b1'>已识别环境:"+RecordApp.Current.Key+"</span>");
};
if(isInstall){
onInstall();
Expand Down
16 changes: 12 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@
}
</style>
<a class="navItem slc" href="https://xiangyuecn.github.io/Recorder/">
<div class="navTitle">Recorder测试</div>
<div class="navDesc">Recorder库使用简单,功能丰富,支持PC、Android,但IOS上仅Safari支持录音</div>
<div class="navTitle">Recorder H5</div>
<div class="navDesc">Recorder H5使用简单,功能丰富,支持PC、Android,但IOS上仅Safari支持录音</div>
</a>

<a class="navItem" href="https://jiebian.life/web/h5/github/recordapp.aspx">
<div class="navTitle">RecordApp测试</div>
<div class="navTitle">RecordApp</div>
<div class="navDesc">RecordApp除Recorder支持的外,支持Hybrid App,IOS上支持微信网页和小程序web-view</div>
</a>
</div>
Expand Down Expand Up @@ -149,6 +149,14 @@
<audio class="recPlay" style="width:100%"></audio>
<div class="reclog"></div>

<hr>
<div class="pd">
【测试App】
IOS Demo App:<a href="https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_ios">下载源码</a> 自行编译

,Android Demo App:<a href="https://xiangyuecn.github.io/Recorder/app-support-sample/demo_android/app-debug.apk.zip" download="app-debug.apk">下载APK</a> (40kb,删除.zip后缀,<a href="https://github.com/xiangyuecn/Recorder/tree/master/app-support-sample/demo_android">源码</a>)
</div>

<hr>
<div class="pd">
<button onclick="goiframe()">把页面放到IFrame里面测试权限请求</button>
Expand Down Expand Up @@ -191,7 +199,7 @@
</pre>
<div>
<hr>
注:录音时注意观察灰色区域是否有绿色音量跳动,没有绿色跳动说明Recorder没有获取到声音数据。如果测试发现mp3没有声音,可以试一下wav格式,如果wav格式有声音,说明内置lamejs mp3编码器有问题。如果都没有,下载下来播放看看有没有。下载下来也没有声音可以反馈一下。
<span style="color:#f60;font-size:16px;font-weight:bold;">问题自检:</span>录音时注意观察灰色区域是否有绿色音量跳动,没有绿色跳动说明Recorder没有获取到声音数据。如果测试发现mp3没有声音,可以试一下wav格式,如果wav格式有声音,说明内置lamejs mp3编码器有问题。如果都没有,下载下来播放看看有没有。下载下来也没有声音可以反馈一下。
</div>
<div style="padding-top:20px">
如果浏览器不能正常录音,并且不确定是不是这个库的问题,可以到 <a href="https://xiangyuecn.github.io/Recorder/assets/ztext_collab-project_videojs-record.html">assets/ztext_collab-project_videojs-record.html</a> 试一下。
Expand Down

0 comments on commit c87f82f

Please sign in to comment.