AudioRecord объект не инициализируется - PullRequest
59 голосов
/ 30 января 2011

В приведенном ниже коде мой audioRecord объект не инициализируется. Я попытался переместить его в метод onCreate и сделал его глобальным. Я зарегистрировал состояние, и это возвращает значение 1, что означает готовность к использованию. Отладчик говорит, что startRecording вызывается для неинициализированного объекта. Также говорится, что не удалось получить источник звука.

Почему я получаю эти ошибки?

    package com.tecmark;

    import java.io.BufferedOutputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import android.app.Activity;
    import android.media.AudioFormat;
    import android.media.AudioRecord;
    import android.media.MediaRecorder;
    import android.os.Bundle;
    import android.os.Environment;
    import android.util.Log;
    import android.view.View;
    import android.widget.TextView;

    public class recorder extends Activity  {

        private Thread thread;
        private boolean isRecording;
        private AudioRecord recorder;
        private FileOutputStream os;
        private BufferedOutputStream bos;
        private DataOutputStream dos;
        private TextView text;
        private int audioSource = MediaRecorder.AudioSource.MIC;
        private int sampleRate = 22050;
        private int channel = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        private int encoding = AudioFormat.ENCODING_PCM_16BIT;
        private int result = 0;
        private int bufferSize;
        private byte[] buffer;

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            Log.v("onCreate", "layout set, about to init audiorec obj");
            text = (TextView)findViewById(R.id.TextView01);

             bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
             buffer = new byte[bufferSize];

            recorder = new AudioRecord(audioSource, sampleRate,channel,encoding,
                    AudioRecord.getMinBufferSize(sampleRate, channel,encoding));
            Log.i("recorder obj state",""+recorder.getRecordingState());
        }

        public void onClickPlay(View v){

        }


        public void record(){
            Log.i("inside record method", "******");
        File path = Environment.getExternalStorageDirectory();
            Log.v("file path", ""+path.getAbsolutePath());

            File file = new File(path, "test.wav");

            if(file.exists()){
            file.delete();
            }

            path.mkdirs();
            Log.v("file path", ""+file.getAbsolutePath());

            try {
             os = new FileOutputStream(file);
             bos = new BufferedOutputStream(os);            
                 dos = new DataOutputStream(bos);        
            } catch (Exception e1) {
             e1.printStackTrace();
            }

            int bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
            byte[] buffer = new byte[bufferSize];
            recorder.startRecording();
            isRecording = true; 
            try{  
                while (isRecording){
            result = recorder.read(buffer, 0, bufferSize);
            for(int a=0; a<result;a++){
                 dos.write(buffer[a]);

                 if(!isRecording){
                   recorder.stop();          
                   break;
                 }

            }

             }
             dos.flush();
             dos.close();
        }catch(Exception e){
             e.printStackTrace();
        }

    }// end of record method

    public void onClickStop(View v){
        Log.v("onClickStop", "stop clicked");
        isRecording=false;
    }   
    public void onClickReverse(View v){
        Log.v("onClickReverse", "reverse clicked");
    } 
    public void onClickRecord(View v){
        Log.v("onClickRecourd", "record clicked, thread gona start");
        text.setText("recording");
        thread = new Thread(new Runnable() {
            public void run() {
                isRecording = true;
                record();
            }
        });

        thread.start();
        isRecording = false;
    }   
}//end of class

Logcat

01-30 15:23:16.724: ERROR/AudioRecord(12817): Could not get audio input for record source 1 01-30 15:23:16.729: 
ERROR/AudioRecord-JNI(12817): Error creating AudioRecord instance: initialization check failed. 01-30 15:23:16.729: 
ERROR/AudioRecord-Java(12817): [ android.media.AudioRecord ] Error code
-20 when initializing native AudioRecord object. 01-30 15:23:16.729: INFO/recorder obj state(12817): 1 01-30 15:23:16.729: 
WARN/dalvikvm(12817): threadid=13: thread exiting with uncaught exception (group=0x4001b180) 01-30 15:23:16.729: 
ERROR/AndroidRuntime(12817): Uncaught handler: thread Thread-7 exiting due to uncaught exception 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord. 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):     at android.media.AudioRecord.startRecording(AudioRecord.java:495) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):     at com.tecmark.recorder.record(recorder.java:114) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):     at com.tecmark.recorder$1.run(recorder.java:175) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):     at java.lang.Thread.run(Thread.java:1096)

Ответы [ 12 ]

92 голосов
/ 26 марта 2011

Хитрость с использованием AudioRecord заключается в том, что у каждого устройства могут быть разные настройки инициализации, поэтому вам придется создать метод, который циклически повторяет все возможные комбинации битрейтов, кодирования и т. Д.

private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
public AudioRecord findAudioRecord() {
    for (int rate : mSampleRates) {
        for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
            for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
                try {
                    Log.d(C.TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
                            + channelConfig);
                    int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                        // check if we can instantiate and have a success
                        AudioRecord recorder = new AudioRecord(AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                        if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
                            return recorder;
                    }
                } catch (Exception e) {
                    Log.e(C.TAG, rate + "Exception, keep trying.",e);
                }
            }
        }
    }
    return null;
}

AudioRecord recorder = findAudioRecord();
recorder.release();
91 голосов
/ 11 мая 2012

У меня была такая же проблема, она была решена путём

<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>

в манифест.

Начиная с Lollipop, вам также нужно специально спрашивать пользователя о каждом разрешении. Как они могли отозвать их. Убедитесь, что разрешение предоставлено.

9 голосов
/ 15 июля 2011

Согласно javadocs, все устройства гарантированно поддерживают этот формат (для записи):

44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT.

Измените на CHANNEL_OUT_MONO для воспроизведения.1005 *

4 голосов
/ 06 ноября 2016

Даже после выполнения всех вышеперечисленных шагов у меня возникла одна и та же проблема, для меня сработало то, что моя операционная система была зефирной, и мне пришлось просить разрешения .

4 голосов
/ 19 апреля 2016

Теперь, с леденцом на палочке, вам нужно специально запрашивать у пользователя каждое разрешение. Убедитесь, что разрешение предоставлено.

3 голосов
/ 01 ноября 2012

Проблема с инициализацией нескольких объектов AudioRecord может быть исправлена ​​с помощью audioRecord.release(); перед созданием следующего объекта ... Подробнее здесь: Android AudioRecord - Не инициализировать второй раз

2 голосов
/ 03 ноября 2017

В моем случае мне пришлось вручную разрешить разрешение в Android 7 для микрофона, как прокомментировал Шон Чжу.

2 голосов
/ 06 мая 2016

Если ваша система мобильной связи - Android M или выше, возможно, вам нужно применить разрешение на запись звука в Android M. http://developer.android.com/guide/topics/security/permissions.html

2 голосов
/ 15 июля 2012

Просто была такая же проблема. Решением было перезагрузить устройство. Во время игры с кодом я не выпускал объект AudioRecord, который явно вызывал зависание аудиоустройства. Чтобы проверить, работает ли аудиоустройство, я скачал Audalyzer из Google Play.

1 голос
/ 19 апреля 2011

Я заметил, что когда SDCard на avd, который я запускаю, заполняется, конструктор AudioRecord возвращает ноль.Вы пытались очистить SDCard?

...