问题:
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;
- }
- }