@Tyhj
        
        2018-11-17T14:17:10.000000Z
        字数 7647
        阅读 2092
    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 dependencydependencies {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() {@Overridepublic void onUpdate(double db, long time) {//根据分贝值来设置录音时话筒图标的上下波动}@Overridepublic 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为录音时长@Overridepublic 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为保存路径@Overridepublic 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,设置背景,显示动画
<ImageViewandroid: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"><itemandroid:id="@android:id/background"android:drawable="@drawable/ic_voice_null" /><item android:id="@android:id/progress"><clipandroid:clipOrientation="vertical"android:drawable="@drawable/ic_voice_full"android:gravity="bottom" /></item></layer-list>
//录音中....db为声音分贝,time为录音时长@Overridepublic void onUpdate(double db, long time) {//根据分贝值来设置录音时话筒图标的上下波动mImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));mTextView.setText(Defined.getDate(time));time_Long=(int)(time/1000);}