Объект AudioRecord не инициализируется

в приведенном ниже коде my 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.run(recorder.java:175) 01-30 15:23:16.739: 
ERROR/AndroidRuntime(12817):     at java.lang.Thread.run(Thread.java:1096)

12 ответов


трюк с использованием 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();

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

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

в манифест.

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


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

44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT.

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


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


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


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


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


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


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


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


Я думаю, что это связано с потоком, не зная, что вы приостановили основную деятельность и все еще пытаетесь записать после того, как вы остановили рекордер.

Я решил это, изменив методы onResume() и onPause (), чтобы изменить логическое значение isRecording.

public void onResume() { 
    ... 
    isRecording = true;
}

public void onPause() { 
    ... 
    isRecording = false;
}

тогда в вашем потоке окружите оба ваших startRecording() и stop() С if-операторы проверки isRecording:

if(isRecording) 
    recorder.startRecording();
...
if(isRecording)
    recorder.stop(); // which you've done

я переписал ответ от @DustinB для всех, кто использует Xamarin Android AudioRecord с C#.

int[] sampleRates = new int[] { 44100, 22050, 11025, 8000 };
Encoding[] encodings = new Encoding[] { Encoding.Pcm8bit, Encoding.Pcm16bit };
ChannelIn[] channelConfigs = new ChannelIn[]{ ChannelIn.Mono, ChannelIn.Stereo };

//Not all of the formats are supported on each device
foreach (int sampleRate in sampleRates) 
{
    foreach (Encoding encoding in encodings) 
    {
        foreach (ChannelIn channelConfig in channelConfigs) 
        {
            try 
            {
                Console.WriteLine("Attempting rate " + sampleRate + "Hz, bits: " + encoding + ", channel: " + channelConfig);
                int bufferSize = AudioRecord.GetMinBufferSize(sampleRate, channelConfig, encoding);

                if (bufferSize > 0) 
                {
                    // check if we can instantiate and have a success
                    AudioRecord recorder = new AudioRecord(AudioSource.Mic, sampleRate, channelConfig, encoding, bufferSize);

                    if (recorder.State == State.Initialized)
                    {
                        mBufferSize = bufferSize;
                        mSampleRate = sampleRate;
                        mChannelConfig = channelConfig;
                        mEncoding = encoding;
                        recorder.Release();
                        recorder = null;
                        return true;
                    }
                }
            } 
            catch (Exception ex) 
            {
                Console.WriteLine(sampleRate + "Exception, keep trying." + ex.Message);
            }
        }
    }
}