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

2015年05月14日 12:11:55 wyyl1 阅读数:26347更多

个人分类: android判断是否禁用了录音权限Android

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wyyl1/article/details/45719099


问题:

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{
 
        @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{
 
        @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;
    }
}
 

更多相关文章

  1. 关于Android中xml布局文件
  2. android 入门xml布局文件
  3. Android 下载文件及写入SD卡
  4. 高焕堂android中文书全,电子文件for version 1.0
  5. Android:关于声明文件中android:process属性说明
  6. android编译时添加库第三方库文件
  7. AndroidManifest.xml文件详解

随机推荐

  1. 跟大家分享下Android布局文件layout.xml
  2. Android(安卓)跑马灯效果auto scroll tex
  3. coreApp="true";android:sharedUserId="an
  4. android中用Spannable在TextView中设置超
  5. Android(安卓)GIS +webservice
  6. Android(安卓)xml资源文件中@、@android:
  7. android XML布局大全
  8. Android(安卓)ApiDemos示例解析(145):Vie
  9. Shape的使用
  10. NetBeans 安装Android(安卓)开发环境