H5页面最终是通过webview展示出来的,通过配置webview,使webview能够识别来自H5中的js请求; 然后webview再调用原生提供的接口实现 h5 与原生交互,反之亦行;
> 音频格式参数json【默认key和value】:
```java
{
"audioRate":"16000",
"channelConfig":"16",
"audioFormat":"1"
"uploadUrl":"http://" // 可选
}
```
其中:
* audioRate: 采样频率字段; 目前使用:16000,默认使用:16000
* channelConfig: 通道设置字段 ;目前只使用:单声道:16,可选值如下:
- 单声道:16
- 多声道传入:12
* audioFormat:文件格式,目前只使用:PCM_16BIT:1,可选值如下:
- PCM 16位:1 【默认】
- PCM 8位:2
- WAV文件:3
- AMR压缩文件:4
- SPX:5
* uploadUrl : 传入需要上传的服务器地址,需要以http开头;
若传入此参数,程序会将生成好的语音文件,上传到指定的url地址,并返回url的响应(最好是json格式),回调给H5的js定义的方法`parseRecordComplete`;
以下为 html 示例代码: !示例html代码
<script type="text/javascript">
// 调用原生开始录
function start () {
var json = '{"audioRate":"16000","channelConfig":"16", "audioFormat" : "1"}'
window.Android.startRecording(json); // 调用webview开放接口开始录音
}
// 调用原生结束
function end() {
window.Android.finishRecording();
}
// android 原生回调 js
function parseRecordComplete(result) { // result 为 startRecording() 时 指定的服务器url回传的信息
if(!/\s+/.test(result)) {
alert("文件已生成: " + result)
}
}
</script>
开始录音 结束录音
H5 需定义一个js方法,供WebView录音完成时,回调H5时用;
用来表示一个操作结束;如 parseRecordComplete(result)
:
function parseRecordComplete(result) { // result 为 startRecording() 时 指定的服务器url回传的信息
// h5 自己的操作
}
注:如果您是H5开发人员,可省略这一步;供Android开发查看
注:因为目前语音识别只支持 PCM 格式,故一些配置不生效。先预留一些配置实现;
// 录音sdk api
private RecordAPI recordAPI;
webView.getSettings().setJavaScriptEnabled(true);
// 支持JavaScript调用,标识符 Android
webView.addJavascriptInterface(new RecordJavaScriptInterface(), "Android");
/**
* JavaScript调用Native 示例代码
*/
private class RecordJavaScriptInterface {
// 路径
String originPath;
// 录音文件上传路径
String uploadUrl = "http://wwww";
/**
* 格式类型
* @param type
* @return
*/
private VoiceType getVoiceType(int type) {
switch (type) {
case 1:
return VoiceType.PCM_16BIT;
case 2:
return VoiceType.PCM_8BIT;
case 3:
return VoiceType.WAV;
case 4:
return VoiceType.AMR;
case 5:
return VoiceType.SPEEX;
}
return VoiceType.PCM_16BIT;
}
/**
* 目前只支持 PCM 无损格式,原因见上
* @param json
* @return
*/
private void initRecordAPI(String json) {
try {
JSONObject object = new JSONObject(json);
// audioRate: 采样频率字段。目前使用:16000
int rate = object.getInt("audioRate");
// 文件格式 (1:PCM_16位,2:PCM_位,3:WAV格式,4:AMR格式,5:SPX格式)
VoiceType voiceType = getVoiceType(object.getInt("audioFormat"));
Object channel;
if (object.getInt("channelConfig") == 16) { // 通道,目前:单声道:16
channel = AudioRecordParam.AudioInChannel.CHANNEL_IN_MONO;
} else {
channel = AudioRecordParam.AudioInChannel.CHANNEL_IN_STEREO;
}
recordAPI = VoiceManager.with(H5TestActivity.this).getRecordAPI(voiceType, new AudioRecordParam(rate, (AudioRecordParam.AudioInChannel) channel));
} catch (Exception e) {
Log.e(H5TestActivity.class.getSimpleName(), e.toString());
}
}
///////////////////////// 与 JS 交互的接口定义如下
@JavascriptInterface
public void startRecording(String json) {
// ===== 1.初始化录音组件
initRecordAPI(json);
if (recordAPI == null) {
Toast.makeText(getApplicationContext(), "录音组件初始化失败,请检查参数设置! " + json, Toast.LENGTH_SHORT).show();
return;
}
try {
// 2. ==== 设置临时文件:开通输出流到指定的文件
File fpath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/better");
fpath.mkdirs();// 创建文件夹
File mAudioFile = new File(fpath, "recoding.wav");
originPath = fpath.getAbsolutePath() + "/recoding.wav";
// 3.==== 判断是否有需要uploadUrl
JSONObject object = new JSONObject(json);
final String uploadUrl = object.optString("uploadUrl");
// 4.=== 开始录音
recordAPI.startRecord(originPath, new RecordListener() {
@Override
public void onStart() {
}
@Override
public void onFinishRecord(long duration, final String filePath) {
Toast.makeText(getApplicationContext(), "录音结束,开始上传文件 " + duration, Toast.LENGTH_SHORT).show();
if (!TextUtils.isEmpty(uploadUrl)) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d("hehe", "开始上传" + filePath);
final String info = UploadUtils.getResponseString(uploadUrl, filePath);
RecordUtils.getMainHandler().post(new Runnable() {
@Override
public void run() {
if (H5TestActivity.this != null && !H5TestActivity.this.isFinishing()) {
// 原生回调 H5 中的 js
webView.loadUrl("javascript:parseRecordComplete('" + info + "')");
}
}
});
}
}).start();
}
}
@Override
public void onCancel() {
}
@Override
public void onError(Exception e) {
Toast.makeText(getApplicationContext(), "出错啦 " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
public void onAmplitudeChanged(int volume) {
}
});
} catch (Exception e) {
Log.e(H5TestActivity.class.getSimpleName(), e.toString());
}
}
@JavascriptInterface
public void finishRecording() {
if (recordAPI != null) {
recordAPI.stopRecord();
}
}
@JavascriptInterface
public void cancelRecording() {
if(recordAPI != null) {
recordAPI.cancelRecord();
}
}