Android AudioRecord initialization fails every time
Asked Answered
P

4

14

My problem is simple to explain -- I am trying to create a AudioRecord object but it fails to initialize (ie after the constructor, getState returns 0, indicating failure). I am running this from Eclipse on a MotoDroid 1 running OS 2.2.1. My AndroidManifest.xml is, AFAIK, using the right permission, RECORD_AUDIO (I don't know how to confirm this):

<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>

I do the following to create the 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() returns 0 (ie STATE_UNINITIALIZED)

I have not found any complete examples of using this API and I'm very much an Android beginner so the solution may well be something simple. What can I do to find out why it fails?

A few people have asked similar questions, but they must have been having different problems than me because the fixes they approve haven't helped me. Most notably this. But the approved solution is perplexing and didn't work for me anyway. I have also tried a variety of bit rates (8000, 16000, 11025, 44100), both mono and stereo and 8 and 16 bit. No combination comes back as successfully initialized.

Pantaloons answered 19/12, 2010 at 10:6 Comment(2)
what does logcat say? also try moving uses-permission out of application. afaik it should sit in manifest.Liddie
For some reason, LogCat stopped showing most of the log info after a few runs -- but that's a whole other problem. I'd flag your uses-permissions comment as the answer... if it was one (because it worked!)Pantaloons
E
42

I spent some hours solving this problem, and found out that moving

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

outside the application block actually solved it!

...
    </application>

    <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
</manifest>
Ennius answered 25/8, 2011 at 9:46 Comment(1)
Moving the user-permission node outside solves it. Thanks man!Devilment
E
7

Another possible issue:

I had the RECORD_AUDIO permission enabled in my manifest, but for API level 23 I had to also request the permission at runtime.

Ellaelladine answered 2/7, 2016 at 20:1 Comment(1)
how did you request permission at runtime?Gladiate
Q
1

Try 16bit. This is what works for me:

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");
    }

And I have the following variables set:

int frequency = 8000;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
Quadrennial answered 19/12, 2010 at 20:2 Comment(2)
I was working with this today and found that it makes a huge difference if you call audioRecord.release() at the end. Apparently the object will not be released until you do this. For some reason, even if audioRecord.release() is called at the end of some code, it will actually work on the first try once it's put in. I have been experimenting and do not understand that, but I have found that it helps big-time with the initialization.Quadrennial
If you download the app Audalyzer and try to run it and it's frozen, you likely have your AudioRecord resources tied up. Restarting the phone fixes that.Quadrennial
I
0

In case anyone needs to request disk permissions manually for API 23+, here's one method that I have used. Just swap in permission.RECORD_AUDIO in the relevant bits. The method logic depends on a few bits that are external (e.g. strings.xml, ActivityCompat, Snackbar), but thought it might help someone anyway.

/**
 * 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);
        }

    }
}
Iggie answered 27/7, 2017 at 20:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.