Подтвердить что ты не робот

Инициализация Android AudioRecord прерывается каждый раз

Моя проблема проста для объяснения - я пытаюсь создать объект 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, поэтому решение может быть чем-то простым. Что я могу сделать, чтобы узнать, почему это не удается?

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

4b9b3361

Ответ 1

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

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

вне блока приложений действительно его решила!

...
    </application>

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

Ответ 2

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

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

Ответ 3

Попробуйте 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;

Ответ 4

В случае, если кто-либо должен запросить разрешения на доступ к диску вручную для 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);
        }

    }
}