Android使用AudioRecord遇到的问题与解决方法


问题:

1、android判断是否禁用了录音权限

      通过判断分贝值是否大于0,在代码中搜索 volume > 0

2、部分手机在调用 audioRecord.startRecording(); 和audioRecord.stop();方法时会抛出异常,例如联想手机

3、部分手机(例如联想)会抛出java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.

      解决方法来源于:http://www.cnblogs.com/mythou/p/3241925.html

       原因:

       

出现上面问题的原因是录音的硬件资源被申请了,但是没有释放,然后你再次申请资源,导致初始化失败。这里需要注意的是不仅仅需要调用Release()方法。还需要把AudioRecord对象置为null,否则还是释放失败。下面是Android 开发网上面的一个对于AudioRecord的释放说明。

Releases the native AudioRecord resources. The object can no longer be used and the reference should be set to null after a call to release()。


解决方法在代码中:


package com.androidleaf.audiorecord;

import android.app.ProgressDialog;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.hisun.phone.core.voice.Device;
import com.todoroo.aacenc.AACEncoder;
import com.todoroo.aacenc.AACToM4A;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

import app.jimu.zhiyu.activity.question.AnswerActivity;

public class AudioRecordUtils {

	private final int audioSource = MediaRecorder.AudioSource.MIC;
	// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
    private final int sampleRateInHz = 16000;
    // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
    private final int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
    // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
    private final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    
    private int inBufSize = 0;
	
	private AudioRecord audioRecord;
	
	private AACEncoder encoder = null;
	
	private ProgressDialog mProgressDialog = null;
	
	private boolean isRecord = false;
	
	private Context mContext;
	/**
	 * 录制的音频文件名称
	 */
	private String mAudioRecordFileName;
	
	private static final int RECORDED_INIT_DELETE = 0;
	
	private static final int RECORDED_COMPLETED_DELETE = 1;

    private Handler mHandler;

	/**
	 * 是否可以录音 true 可以录音
	 */
	private boolean recordEnable = false;
	
	public AudioRecordUtils(Context context,String audioRecordFileName, Handler handler){
		mContext = context;
		mAudioRecordFileName = audioRecordFileName;
        mHandler = handler;
		initAudioRecord();
	}
    
	/**
	 * 初始化对象
	 */
    private void initAudioRecord(){
		
		inBufSize = AudioRecord.getMinBufferSize(
				sampleRateInHz, 
				channelConfig, 
				audioFormat);
		
		audioRecord  = new AudioRecord(
				audioSource, 
				sampleRateInHz, 
				channelConfig, 
				audioFormat, 
				inBufSize);
		
		encoder = new AACEncoder();
		deleteAllFiles(RECORDED_INIT_DELETE);
		
		mProgressDialog = new ProgressDialog(mContext);
		mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		mProgressDialog.setCanceledOnTouchOutside(false);
		mProgressDialog.setCancelable(false);
		mProgressDialog.setTitle("提示");
		mProgressDialog.setMessage("正在保存录音,请耐心等候......");
		
	}
    
    /**
	 * 开始录音
	 */
	public void startRecord(){
		new AudioRecordTask().execute();
	}
	
	/**
	 * 暂停录音
	 */
	public void pauseRecord(){
		isRecord = false;
	}
	
	/**
	 * 停止录音
	 */
	public void stopRecord(){
		new AudioEncoderTask().execute();
	}
	
	/**
	 * 重新录制
	 */
	public void reRecord(){
		//重新录制时,删除录音文件夹中的全部文件
		deleteAllFiles(RECORDED_INIT_DELETE);
	} 
	
	private void encodeAudio(){
		try {
			//读取录制的pcm音频文件
	    	DataInputStream mDataInputStream = new DataInputStream(new FileInputStream(
	    			FileUtils.getPcmFilePath(mAudioRecordFileName)));
				byte[] b = new byte[(int) new File(FileUtils.
						getPcmFilePath(mAudioRecordFileName)).length()];
				mDataInputStream.read(b);
				//初始化编码配置
				encoder.init(32000, 2, sampleRateInHz, 16, FileUtils.
						getAAcFilePath(mAudioRecordFileName));
				//对二进制代码进行编码
		        encoder.encode(b);
		        //编码完成
		        encoder.uninit();
		        //关闭流
		        mDataInputStream.close();
		        try {
		        	//将aac文件转码成m4a文件
		            new AACToM4A().convert(mContext, FileUtils.getAAcFilePath(mAudioRecordFileName), 
		            		FileUtils.getM4aFilePath(mAudioRecordFileName));
		        } catch (IOException e) {
		            Log.e("ERROR", "error converting", e);
		        }
		        deleteAllFiles(RECORDED_COMPLETED_DELETE);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
	}
	
	class AudioRecordTask extends AsyncTask<Void, Void, Void>{

		@Override
		protected Void doInBackground(Void... params) {
			// TODO Auto-generated method stub
			if(audioRecord == null){
				initAudioRecord();
			}
			RandomAccessFile mRandomAccessFile = null;
			try {
				mRandomAccessFile = new RandomAccessFile(new File(
						FileUtils.getPcmFilePath(mAudioRecordFileName)), "rw");
				byte[] b = new byte[inBufSize/4];
				//开始录制音频
				try{
					// 防止某些手机崩溃,例如联想
					audioRecord.startRecording();
				}catch (IllegalStateException e){
					e.printStackTrace();
				}

				//判断是否正在录制
				isRecord = true;
                long wait = 0;
                long maxWait = 10;
				while(isRecord){
                    //r是实际读取的数据长度,一般而言r会小于buffersize
                    int r = audioRecord.read(b, 0, b.length);
                    long v = 0;
                    // 将 buffer 内容取出,进行平方和运算
                    for (int i = 0; i < b.length; i++) {
                         v += b[i] * b[i];
                    }
                    // 平方和除以数据总长度,得到音量大小。
                    double mean = v / (double) r;
                    double volume = 10 * Math.log10(mean);

                    wait++;
                    if(wait > maxWait){
                        wait = 0;
                        Log.d(this.getClass().getName(), "分贝值:" + volume + " " + (volume > 0));
						if(volume > 0){
							recordEnable = true;
						}
                        Message msg = new Message();
                        msg.what = AnswerActivity.STATUS_PREPARE;
                        Bundle bundle = new Bundle();
                        bundle.putDouble(Device.VOICE_AMPLITUDE, volume);
                        msg.obj = bundle;
                        mHandler.sendMessage(msg);
                    }

					//向文件中追加内容
					mRandomAccessFile.seek(mRandomAccessFile.length());
					mRandomAccessFile.write(b, 0, b.length);
                }
				//停止录制
				try {
					// 防止某些手机崩溃,例如联想
					audioRecord.stop();
					// 彻底释放资源
					audioRecord.release();
					audioRecord = null;
				}catch (IllegalStateException e){
					e.printStackTrace();
				}
				mRandomAccessFile.close();
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}
	}
	
	class AudioEncoderTask extends AsyncTask<Void, Void, Long>{

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			if(mProgressDialog != null && !mProgressDialog.isShowing()){
//				mProgressDialog.show();
                Message msg = new Message();
                msg.what = 2;
                mHandler.sendMessage(msg);
			}
		}

		@Override
		protected Long doInBackground(Void... params) {
			// TODO Auto-generated method stub
			encodeAudio();
			return null;
		}

		@Override
		protected void onPostExecute(Long result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
			if(mProgressDialog.isShowing()){
				mProgressDialog.cancel();
				mProgressDialog.dismiss();
			}
		}
	}
	
	/**
	 * 清空音频录制文件夹中的所有文件
	 * @param isRecorded
	 */
	public void deleteAllFiles(int isRecorded){
		 File[] files = new File(FileUtils.getAudioRecordFilePath()).listFiles();
		switch (isRecorded) {
		case RECORDED_INIT_DELETE:
			for(File file: files){
	        	file.delete();
	        }
			break;
		case RECORDED_COMPLETED_DELETE:
	        for(File file: files){
	        	if(!file.getName().equals(mAudioRecordFileName + Constants.M4A_SUFFIX)){
	        		file.delete();
	        	}
	        }
			break;
		default:
			break;
		}
	}

	public boolean isRecordEnable() {
		return recordEnable;
	}
}


  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值