@Tyhj
2018-11-17T22:17:10.000000Z
字数 7647
阅读 1765
Android
录音两个需要注意的地方,一是录音过短的时候会失败,所以要监听录音时间长短,小于一秒的时候就显示失败;二是录音的时候关闭其他声音
Step 1. Add the JitPack repository to your build file
//Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
//Add the dependency
dependencies {
implementation 'com.github.tyhjh:AudioRecording:v1.0.0'
}
//设置录音保存位置
AudioRecordUtil.init(Environment.getExternalStorageDirectory() + "/audio/");
recordUtil = AudioRecordUtil.getInstance();
//开始录音
recordUtil.startRecord(MainActivity.this);
//取消录音,时间太短须取消
recordUtil.cancelRecord(MainActivity.this);
//结束录音(保存录音文件)
recordUtil.stopRecord(MainActivity.this);
//录音监听
AudioRecordUtil.getInstance().setOnAudioStatusUpdateListener(new AudioRecordUtil.OnAudioStatusUpdateListener() {
@Override
public void onUpdate(double db, long time) {
//根据分贝值来设置录音时话筒图标的上下波动
}
@Override
public void onStop(final String filePath) {
//获取录音文件
}
});
录音时候关闭或开启其他声音
public static boolean muteAudioFocus(Context context, boolean bMute) {
if (context == null) {
Log.d("ANDROID_LAB", "context is null.");
return false;
}
boolean bool = false;
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
//关闭声音
if (bMute) {
int result = am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
bool = result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
} else {
//恢复声音
int result = am.abandonAudioFocus(null);
bool = result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
Log.d("ANDROID_LAB", "pauseMusic bMute=" + bMute + " result=" + bool);
return bool;
}
一个录音的类
package tools;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import java.io.File;
import java.io.IOException;
public class AudioRecoderUtils {
//文件路径
private String filePath;
//文件夹路径
private String FolderPath;
private MediaRecorder mMediaRecorder;
private final String TAG = "fan";
public static final int MAX_LENGTH = 1000 * 60 * 10;// 最大录音时长1000*60*10;
private OnAudioStatusUpdateListener audioStatusUpdateListener;
/**
* 文件存储默认sdcard/record
*/
public AudioRecoderUtils(){
//默认保存路径为/sdcard/record/下
this(Environment.getExternalStorageDirectory()+"/ASchollMsg/record/");
}
public AudioRecoderUtils(String filePath) {
File path = new File(filePath);
if(!path.exists())
path.mkdirs();
this.FolderPath = filePath;
}
private long startTime;
private long endTime;
/**
* 开始录音 使用amr格式
* 录音文件
* @return
*/
public String startRecord() {
// 开始录音
/* ①Initial:实例化MediaRecorder对象 */
if (mMediaRecorder == null)
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setOnErrorListener(null);
try {
/* ②setAudioSource/setVedioSource */
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
/* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
/*
* ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
* ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
*/
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
filePath = FolderPath + Defined.getTimeName() + ".amr" ;
/* ③准备 */
mMediaRecorder.setOutputFile(filePath);
mMediaRecorder.setMaxDuration(MAX_LENGTH);
mMediaRecorder.prepare();
/* ④开始 */
mMediaRecorder.start();
// AudioRecord audioRecord.
/* 获取开始时间* */
startTime = System.currentTimeMillis();
updateMicStatus();
Log.e("fan", "startTime" + startTime);
} catch (IllegalStateException e) {
Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
} catch (IOException e) {
Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
}
return filePath;
}
/**
* 停止录音
*/
public long stopRecord() {
if (mMediaRecorder == null)
return 0L;
endTime = System.currentTimeMillis();
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
audioStatusUpdateListener.onStop(filePath);
filePath = "";
return endTime - startTime;
}
/**
* 取消录音
*/
public void cancelRecord(){
if(mMediaRecorder==null)
return;
mMediaRecorder.setOnErrorListener(null);
mMediaRecorder.setPreviewDisplay(null);
try {
mMediaRecorder.stop();
}catch (Exception e){
e.printStackTrace();
}
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
File file = new File(filePath);
if (file.exists())
file.delete();
filePath = "";
}
private final Handler mHandler = new Handler();
private Runnable mUpdateMicStatusTimer = new Runnable() {
public void run() {
updateMicStatus();
}
};
private int BASE = 1;
private int SPACE = 100;// 间隔取样时间
public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {
this.audioStatusUpdateListener = audioStatusUpdateListener;
}
/**
* 更新麦克状态
*/
private void updateMicStatus() {
if (mMediaRecorder != null) {
double ratio = (double)mMediaRecorder.getMaxAmplitude() / BASE;
double db = 0;// 分贝
if (ratio > 1) {
db = 20 * Math.log10(ratio);
if(null != audioStatusUpdateListener) {
audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis()-startTime);
}
}
mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
}
}
public interface OnAudioStatusUpdateListener {
/**
* 录音中...
* @param db 当前声音分贝
* @param time 录音时长
*/
public void onUpdate(double db, long time);
/**
* 停止录音
* @param filePath 保存路径
*/
public void onStop(String filePath);
}
}
调用录音的类并实现其中的方法
//录音回调
mAudioRecoderUtils.setOnAudioStatusUpdateListener(new AudioRecoderUtils.OnAudioStatusUpdateListener() {
//录音中....db为声音分贝,time为录音时长
@Override
public void onUpdate(double db, long time) {
//根据分贝值来设置录音时话筒图标的上下波动,下面有讲解
mImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
mTextView.setText(Defined.getDate(time));
time_Long=(int)(time/1000);
}
//录音结束,filePath为保存路径
@Override
public void onStop(String filePath) {
//发送语音
JSONObject json = null;
Defined.muteAudioFocus(SendMessage.this,false);
try {
json = new JSONObject(getJson.getMsg("null", 2, time_Long, getString(R.string.singleTalk), linkMan.getId()));
Messge messge = new Messge(json);
messge.setSoundPath(filePath);
updateView(messge);
sendVoice(filePath,messges.size()-1);
} catch (JSONException e) {
e.printStackTrace();
}
mTextView.setText("00:00");
}
});
//录音
Defined.muteAudioFocus(SendMessage.this,true);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
y=event.getRawY();
time = System.currentTimeMillis();
mPop.showAtLocation(ll_bg, Gravity.CENTER,0,0);
try {
mAudioRecoderUtils.startRecord();
}catch (RuntimeException e){
e.printStackTrace();
Snackbar.make(iv_sound,"先允许调用系统录音权限",Snackbar.LENGTH_SHORT).show();
}
iv_sound.startAnimation(expend);
break;
case MotionEvent.ACTION_UP:
if(System.currentTimeMillis()-time<1000){
Snackbar.make(iv_sound,"录音时间过短,请重试",Snackbar.LENGTH_SHORT).show();
mAudioRecoderUtils.cancelRecord();
mPop.dismiss();
iv_sound.startAnimation(noexpend);
break;
}else if(y-event.getRawY()>300){
Snackbar.make(iv_sound,"已取消发送语音",Snackbar.LENGTH_SHORT).show();
mAudioRecoderUtils.cancelRecord();
mPop.dismiss();
iv_sound.startAnimation(noexpend);
break;
}else {
try{
mAudioRecoderUtils.stopRecord(); //结束录音(保存录音文件)
}catch (Exception e){
e.printStackTrace();
Snackbar.make(iv_sound,"先允许调用系统录音权限",Snackbar.LENGTH_SHORT).show();
}
mPop.dismiss();
iv_sound.startAnimation(noexpend);
break;
}
case MotionEvent.ACTION_CANCEL:
mAudioRecoderUtils.cancelRecord(); //取消录音(不保存录音文件)
mPop.dismiss();
iv_sound.startAnimation(noexpend);
break;
}
关于录音的时候显示语音声音大小动画
一个ImageView,设置背景,显示动画
<ImageView
android:id="@+id/zeffect_recordbutton_dialog_imageview"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/zeffect_recordbutton_micrphone" />
其中src也是一个xml文件,xml里面的drawable是两张颜色不一样形状一样的图片,我用的是矢量图片。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@android:id/background"
android:drawable="@drawable/ic_voice_null" />
<item android:id="@android:id/progress">
<clip
android:clipOrientation="vertical"
android:drawable="@drawable/ic_voice_full"
android:gravity="bottom" />
</item>
</layer-list>
//录音中....db为声音分贝,time为录音时长
@Override
public void onUpdate(double db, long time) {
//根据分贝值来设置录音时话筒图标的上下波动
mImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
mTextView.setText(Defined.getDate(time));
time_Long=(int)(time/1000);
}