由于项目需要在一个使用了WebView控件的网页上实现本地录音的功能,以下为部分步骤:
1.在MainActivity类中添加如下成员变量:
private MediaRecorder recorder; // 录音类
private String fileName; // 录音生成的文件存储路径
2.添加权限
①在AndroidManifest.xml文件中添加如下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
②在onCreate函数中检查这些权限(该操作仅针对安卓6.0及以上的用户,低版本用户可能不需要这一步)
onCreate函数中请求权限
requestPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
requestPermission(Manifest.permission.RECORD_AUDIO);
requestPermission函数如下:
private void requestPermission(String permission){
if(ContextCompat.checkSelfPermission(this, permission)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{permission}, 0);
}
}
3.onCreate函数中初始化录音文件存储路径
fileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/audiorecordertest.amr";
4.开始录音函数,创建录音对象并进行设置
public boolean startRecord() {
recorder = new MediaRecorder();
try {
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
}catch (IllegalStateException e){
Log.i(LOG_TAG, "设置录音源失败");
e.printStackTrace();
}
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setOutputFile(fileName);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
recorder.prepare();
}catch (IOException e){
Log.e(LOG_TAG, "准备失败");
e.printStackTrace();
}
recorder.start();
Log.i(LOG_TAG, "开始录音...");
return true;
}
5.停止录音函数
public void stopRecord() {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
Log.i(LOG_TAG, "停止录音");
}
6.以上安卓的本地Java代码,在网页端需要调用这些方法来实现本地录音功能
7.当完成录音后,录音内容会存储在fileName变量对应的本地文件中,此时需要将该文件取出到前端web页面中,然后完成文件上传
首先需要在web页面中嵌入一个隐藏的表单来获取文件:
<form id="submit-file" style="display: hidden;" action="upload_file.php" method="post" enctype="multipart/form-data">
<input id="ttt" type="file" name="file" accept="audio/amr" />
</form>
然后模拟一次文件选择和表单提交操作,将文件获取到前台来,并上传文件内容。
引入相关js文件:
<script src="jquery-3.2.1.js"></script>
<script src="jquery-form.js"></script>
模拟选择文件并上传:
// 获取录音文件并上传
$("#ttt").trigger("click");
window.setTimeout(function(){
$("#submit-file").ajaxSubmit(function(message) {
$("body").append("<p>"+message+"</p>");
});
}, 3000);
其中延时三秒是为了确保文件已经由后台传输至前台页面,同时ajax提交会只提交表单而不会发生跳转。其中模拟点击事件会触发webview本地的onFileChooser函数,具体如下:
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
result.confirm(JSBridge.callJsPrompt(MainActivity.this, webView, message));
return true;
}
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
File f = new File(fileName);
if(f.exists()){
Uri u = Uri.fromFile(f);
filePathCallback.onReceiveValue(new Uri[]{u});
}
return true;
}
});
8.服务器端需要对上传的文件接收并进行转码,由于录音生成到的是amr文件,通过ffmpeg可以转码成mp3文件。服务器端php代码如下:
<?php
if ($_FILES ["file"] ["error"] > 0) {
echo "Return Code: " . $_FILES ["file"] ["error"] . "<br />";
} else {
if (file_exists ( "upload/" . $_FILES ["file"] ["name"] )) {
echo $_FILES ["file"] ["name"] . " already exists. ";
} else {
move_uploaded_file ( $_FILES ["file"] ["tmp_name"], "upload/" . $_FILES ["file"] ["name"] );
// TODO 文件转码,此处需要重新设计生成的文件的名称
exec("upload\\ffmpeg.exe -i upload\\audiorecordertest.amr "."upload\\1.mp3");
// 直接返回文件存储的路径,并将其构建成一个audio元素
echo "<audio src='http://192.168.250.191/android_test/assets/upload/1.mp3' controls='controls'>";
}
}
?>