При инициализации Android AudioRecord каждый раз происходит сбой - PullRequest
12 голосов
/ 19 декабря 2010

Моя проблема проста для объяснения - я пытаюсь создать объект AudioRecord, но он не может инициализироваться (т.е. после конструктора getState возвращает 0, что указывает на ошибку). Я запускаю это из Eclipse на MotoDroid 1 под управлением ОС 2.2.1. Мой AndroidManifest.xml, AFAIK, использует правильное разрешение RECORD_AUDIO (я не знаю, как это подтвердить):

<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <activity android:name=".SphinxMic"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

Для создания AudioRecord я делаю следующее:

bufferSize = AudioRecord.getMinBufferSize(8000, CHANNEL_IN_MONO, ENCODING_PCM_8BIT);
audioRecorder = new AudioRecord(AudioSource.MIC, 8000, CHANNEL_IN_MONO, ENCODING_PCM_8BIT, 50*bufferSize);
if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED)
  throw new Exception("AudioRecord init failed");

audioRecorder.getState () возвращает 0 (т. Е. STATE_UNINITIALIZED)

Я не нашел полных примеров использования этого API, и я очень новичок в Android, поэтому решение вполне может быть чем-то простым. Что я могу сделать, чтобы выяснить, почему это не удается?

Несколько человек задавали похожие вопросы, но у них, должно быть, были другие проблемы, чем у меня, потому что исправления, которые они одобрили, не помогли мне. В первую очередь это . Но одобренное решение вызывает недоумение и все равно не работает для меня. Я также пробовал различные скорости передачи данных (8000, 16000, 11025, 44100), как моно, так и стерео, а также 8 и 16 бит. Ни одна комбинация не возвращается как успешно инициализированная.

Ответы [ 4 ]

38 голосов
/ 25 августа 2011

Я потратил несколько часов на решение этой проблемы и обнаружил, что перемещение

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

вне блока приложения фактически решило это!

...
    </application>

    <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
</manifest>
6 голосов
/ 02 июля 2016

Другая возможная проблема:

В моем манифесте было разрешено разрешение RECORD_AUDIO, но для уровня API 23 мне также пришлось запрашивать разрешение во время выполнения.

1 голос
/ 19 декабря 2010

Попробуйте 16 бит.Вот что у меня работает:

try {
        // Create a new AudioRecord object to record the audio.
        bufferSize = AudioRecord.getMinBufferSize(frequency,channelConfiguration,audioEncoding);

        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                                                  frequency, channelConfiguration, 
                                                  audioEncoding, bufferSize);
    } catch (Throwable t) {
        Log.e("AudioRecord","Recording Failed");
    }

И у меня установлены следующие переменные:

int frequency = 8000;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
0 голосов
/ 27 июля 2017

В случае, если кому-то потребуется запросить права доступа к диску для API 23+, вот один из методов, который я использовал. Просто поменяйте permission.RECORD_AUDIO на соответствующие биты. Логика метода зависит от нескольких битов, которые являются внешними (например, strings.xml, ActivityCompat, Snackbar), но думают, что в любом случае это может кому-то помочь.

/**
 * Requests the Storage permissions.
 * If the permission has been denied previously,
 * a SnackBar will prompt the user to grant the
 * permission, otherwise it is requested directly.
 */
private void requestStoragePermissions() {

    // Newer versions Android 18+
    if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
        /**
         * Permissions required to read and write storage.
         */
        final String[] PERMISSIONS_STORAGE = {
                permission.READ_EXTERNAL_STORAGE,
                permission.WRITE_EXTERNAL_STORAGE,
        };

        final boolean readResult =
                ActivityCompat.shouldShowRequestPermissionRationale(
                        this, permission.READ_EXTERNAL_STORAGE);
        final boolean writeResult =
                ActivityCompat.shouldShowRequestPermissionRationale(
                        this, permission.WRITE_EXTERNAL_STORAGE);

        if (readResult || writeResult) {

            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example, if the request has been denied previously.
            Log.i(TAG,
                    "Displaying disk permission rationale to provide additional context.");

            // Display a SnackBar with an explanation and a button to trigger the request.
            Snackbar.make(mainView, R.string.permission_storage_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ActivityCompat
                                    .requestPermissions(MainActivity.this,
                                            PERMISSIONS_STORAGE,
                                            REQUEST_STORAGE);
                        }
                    })
                    .show();
        } else {
            // Storage permissions have not been granted. Request them directly.
            ActivityCompat.requestPermissions(
                    this, PERMISSIONS_STORAGE, REQUEST_STORAGE);
        }

    }
}
...