Click here to Skip to main content
15,887,676 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am working on an android app in which I want to record user voice in wav format and do processing on it. I want sample rate of 22050Hz and 16 bit signed format with mono channel. I got some code by searching on google and integrated the same in my app but as I run my app it gives me 3 errors:

E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.


I have added the permission in the manifest but the error persists.

1. Wavrecordnew.java

Java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.TimerTask;
import java.util.Timer;
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.os.Handler;
import android.view.View;
import android.widget.Button;

public class Wavrecordernew {
    private static final int RECORDER_BPP = 16;
    private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
    private static final String AUDIO_RECORDER_FOLDER = "Automator";
    private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
    private static final int RECORDER_SAMPLERATE = 22050;
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

    private static AudioRecord recorder = null;
    private static int bufferSize = 0;
    //bufferSize *= 2;
    private static Thread recordingThread = null;
    private static boolean isRecording = false;
    private static String filenme,wavpath;

   // bufferSize = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);


    private static String getFilename(){
        String filepath = wavpath;
        File file = new File(filepath,AUDIO_RECORDER_FOLDER);

        if(!file.exists()){
            file.mkdirs();
        }

        return (file.getAbsolutePath() + "/" + filenme);
    }

    private static String getTempFilename(){
        String filepath = wavpath;
        File file = new File(filepath,AUDIO_RECORDER_FOLDER);

        if(!file.exists()){
            file.mkdirs();
        }

        File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);

        if(tempFile.exists())
            tempFile.delete();

        return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
    }

    public static void startRecording(String filepathfrmdis, String filenamefrmdis){

        bufferSize = (AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT))*200;
        filenme = filenamefrmdis;
        wavpath = filepathfrmdis;
        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);

        int i = recorder.getState();
        if(i==1)
            recorder.startRecording();

        isRecording = true;

        recordingThread = new Thread(new Runnable() {

            @Override
            public void run() {
                writeAudioDataToFile();
            }
        },"AudioRecorder Thread");

        recordingThread.start();

        new java.util.Timer().schedule(
                new java.util.TimerTask() {
                    @Override
                    public void run() {
                       stopRecording();
                    }
                },
                9000
        );

    }

    private static void writeAudioDataToFile(){
        byte data[] = new byte[bufferSize];
        String filename = getTempFilename();
        FileOutputStream os = null;

        try {
            os = new FileOutputStream(filename);
        } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
            e.printStackTrace();
        }

        int read = 0;

        if(null != os){
            while(isRecording){
                read = recorder.read(data, 0, bufferSize);

                if(AudioRecord.ERROR_INVALID_OPERATION != read){
                    try {
                        os.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void stopRecording(){
        if(null != recorder){
            isRecording = false;

            int i = recorder.getState();
            if(i==1)
                recorder.stop();
            recorder.release();

            recorder = null;
            recordingThread = null;
        }

        copyWaveFile(getTempFilename(),getFilename());
        deleteTempFile();
    }


    private static void deleteTempFile() {
        File file = new File(getTempFilename());

        file.delete();
    }

    private static void copyWaveFile(String inFilename,String outFilename){
        FileInputStream in = null;
        FileOutputStream out = null;
        long totalAudioLen = 0;
        long totalDataLen = totalAudioLen + 36;
        long longSampleRate = RECORDER_SAMPLERATE;
        int channels = 2;
        long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;

        byte[] data = new byte[bufferSize];

        try {
            in = new FileInputStream(inFilename);
            out = new FileOutputStream(outFilename);
            totalAudioLen = in.getChannel().size();
            totalDataLen = totalAudioLen + 36;

            //AppLog.logString("File size: " + totalDataLen);

            WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                    longSampleRate, channels, byteRate);

            while(in.read(data) != -1){
                out.write(data);
            }

            in.close();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void WriteWaveFileHeader(
            FileOutputStream out, long totalAudioLen,
            long totalDataLen, long longSampleRate, int channels,
            long byteRate) throws IOException {

        byte[] header = new byte[44];

        header[0] = 'R'; // RIFF/WAVE header
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        header[4] = (byte) (totalDataLen & 0xff);
        header[5] = (byte) ((totalDataLen >> 8) & 0xff);
        header[6] = (byte) ((totalDataLen >> 16) & 0xff);
        header[7] = (byte) ((totalDataLen >> 24) & 0xff);
        header[8] = 'W';
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        header[12] = 'f'; // 'fmt ' chunk
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        header[16] = 16; // 4 bytes: size of 'fmt ' chunk
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        header[20] = 1; // format = 1
        header[21] = 0;
        header[22] = (byte) channels;
        header[23] = 0;
        header[24] = (byte) (longSampleRate & 0xff);
        header[25] = (byte) ((longSampleRate >> 8) & 0xff);
        header[26] = (byte) ((longSampleRate >> 16) & 0xff);
        header[27] = (byte) ((longSampleRate >> 24) & 0xff);
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        header[32] = (byte) (2 * 16 / 8); // block align
        header[33] = 0;
        header[34] = RECORDER_BPP; // bits per sample
        header[35] = 0;
        header[36] = 'd';
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        header[40] = (byte) (totalAudioLen & 0xff);
        header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
        header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
        header[43] = (byte) ((totalAudioLen >> 24) & 0xff);

        out.write(header, 0, 44);
    }

}


2. DisplayRecordingMessageActivity.java (Calling to wave recorder)

Java
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.io.File;

public class DisplayRecordingMessageActivity extends AppCompatActivity {
    public final static String EXTRA_MESSAGE_USER_NAME = "com.mycompany.myfirstapp.MESSAGE";
    private static Wavrecordernew mRecorder;
    //private static Wavrecordernew mRecordernew;
    private static int filenum = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display_recording_message);

        Intent intentrecordingtranfred = getIntent();
        String message = intentrecordingtranfred.getStringExtra(MyActivity.EXTRA_MESSAGE_RECORDING);
        TextView textView = (TextView) findViewById(R.id.recorderintructionstxtView);
        textView.setText(message);
        textView.setTextSize(16);

    }

    /** Called when the user clicks the Save button */
    public void saveusername(View view) {

        EditText editUsername = (EditText) findViewById(R.id.edit_username);
        String username = editUsername.getText().toString();

        if (!("").equals(username)) {

            String filename = username + filenum + ".wav";
            String wavfilepath = this.getFilesDir().getPath();

            mRecorder.startRecording(wavfilepath,filename);

        }
        else
        {
            //popup saying please enter username and press save
            AlertDialog.Builder builder1 = new AlertDialog.Builder(DisplayRecordingMessageActivity.this);
            builder1.setTitle("Invalid");
            builder1.setMessage("Please Enter your name and then press save");
            builder1.setCancelable(false);
            //builder1.setIcon(R.drawable.delete);
            builder1.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });

            AlertDialog alert11 = builder1.create();
            alert11.show();
        }
    }

}


3. AndroidManifest.xml

XML
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.automator.automator">

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MyActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".DisplayRecordingMessageActivity"
            android:label="@string/title_activity_display_recording_message"
            android:parentActivityName=".MyActivity"
            android:theme="@style/AppTheme.NoActionBar">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="in.automator.automator.MyActivity" />

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

</manifest>


I am looking for solutions since last 5 days.

Thanks in advance.
Posted
Updated 18-Sep-18 23:55pm
Comments
Richard MacCutchan 1-Jan-16 12:36pm    
What do those error codes mean?
prafull agrawal 1-Jan-16 12:44pm    
If I did know, why would I asked here?
Richard MacCutchan 2-Jan-16 3:10am    
How do you expect anyone here to know what they mean? We have no idea where this code came from that you found on the internet, or who wrote it.
prafull agrawal 2-Jan-16 6:02am    
Hi these errors are regarding AudioRecorder class of android itself, and I posted the entire code here for coders reference, if you don't know android then please don't look into it. Thnaks
Richard MacCutchan 2-Jan-16 7:49am    
If you want help with this issue then please provide complete details, rather than dumping all your code and expecting other people to do the debugging.

I would suggest you 2 things here:

1. Use
XML
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
before </application> tag, not after of it.

2. Have you run this once and not called recordInstance.release()? If so you may have tied up audio resources and it will likely not work until you restart the phone.
 
Share this answer
 
v2
Comments
prafull agrawal 3-Jan-16 14:58pm    
Thanks For answer I tried using step 1 but it gave me following errors and the the code didn't ran for once also so no issue with tying up the resources.

E/AudioRecord: Could not get audio input for record source 1, sample rate 22050, format 0x1, channel mask 0x10, session 40, flags 0
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -22.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.
ridoy 3-Jan-16 15:18pm    
Then possible solution would be point 2 of my answer. There may be few other things, you can follow these and investigate yours: http://stackoverflow.com/questions/4843739/audiorecord-object-not-initializing, http://stackoverflow.com/questions/8972858/errors-when-recording-sound-in-android, http://stackoverflow.com/questions/4807428/audiorecord-could-not-get-audio-input-for-record-source-1
prafull agrawal 3-Jan-16 15:54pm    
As the recordInstance is not initialized before it's the 1st time I am using it and it's giving me same error. So I think point 2 won't be the case. Thanks.
prafull agrawal 4-Jan-16 15:14pm    
I managed to resolve above error i.e. E/AudioRecord: Could not get audio input for record source 1, sample rate 22050, format 0x1, channel mask 0x10, session 40, flags 0
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -22.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.

But the old one is back I mean the errors I mentioned in the question are back. No luck.
You should use this method for your problem.


Java
@RequiresApi(api = Build.VERSION_CODES.M)
public void getPermissionToRecordAudio() {
    // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid
    // checking the build version since Context.checkSelfPermission(...)
    // 2) Always check for permission (even if permission has already been granted)
    // since the user can revoke permissions at any time through Settings
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {

        // The permission is NOT already granted.
        // Check if the user has been asked about this permission already and denied
        // it. If so, we want to give more explanation about why the permission is needed.
        // Fire off an async request to actually get the permission
        // This will show the standard permission request dialog UI
        requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                RECORD_AUDIO_REQUEST_CODE);

    }
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900