Question

I am relatively new to android programming and need a bit of help with this. I am coding an app that records audio but the code crashes when I run the recording code.

Here is the error reported when the app crashes...

04-29 19:02:24.833 30257-30257/com.deemo.taglist E/AudioRecordTest﹕ prepare() failed 04-29 19:02:24.833 30257-30257/com.deemo.taglist E/MediaRecorder﹕ start called in an invalid state: 4 04-29 19:02:24.843 30257-30257/com.deemo.taglist E/AndroidRuntime﹕ FATAL EXCEPTION: main java.lang.IllegalStateException at android.media.MediaRecorder.start(Native Method) at com.deemo.taglist.acts.BpcAct.startRecording(BpcAct.java:335) at com.deemo.taglist.acts.BpcAct.onClick(BpcAct.java:498) at android.view.View.performClick(View.java:4191) at android.view.View$PerformClick.run(View.java:17184) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method)

...and here is the ENTIRE activity where the audio recording is executed:

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.wesoft.songscrapbook.mods.DataModel;
import com.wesoft.songscrapbook.R;
import com.wesoft.songscrapbook.misc.SongChords;
import com.wesoft.songscrapbook.misc.SongStruct;
import com.wesoft.songscrapbook.misc.SsbAtt;
import com.wesoft.songscrapbook.utils.BestScaler;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class BpcAct extends Activity implements View.OnClickListener {

BestScaler newScaler = new BestScaler();
private boolean scalingComplete = false;

SsbAtt btnAttributes = new SsbAtt();
DataModel dataModel = new DataModel();

// File ssAudioPath;
ProgressBar recordAudioGuidePB;
EditText songTitle, songLyrics;
Button startRecordBtn, stopRecordBtn, startPlaybackBtn, stopPlaybackBtn, deleteAudioBtn, defineChordsBtn, goToReviewBtn, exitToMainBtn;
TextView songDate, audioCheck, songStructure, songIntroChords, songVerseChords, songChorusChords, songBridgeChords, songOutroChords, audioGuideDuration, audioGuidePBarFill, audioGuideFilePath;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Hide the Title Bar of the Application --> Must come before setting the Layout. \\
    requestWindowFeature(Window.FEATURE_NO_TITLE);

    // Hide the Status Bar of Android OS --> Can also be done later. \\
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    // Now you can draw the first Layout --> HomeScreen of the Application. \\
    setContentView(R.layout.act_bpc_lyt);

    // Prevent the onboard keyboard from popping up automatically. \\
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);


    // Instantiate (or get references to) all buttons laid out in this Activity. \\
    songTitle = (EditText) findViewById(R.id.song_Title_Input_ET);                        // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songLyrics = (EditText) findViewById(R.id.song_Lyrics_Input_ET);                      // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songDate = (TextView) findViewById(R.id.song_Creation_Date_TV);                       // Do not DELETE. Needed for the 'DataModel.java' class. \\
    audioCheck = (TextView) findViewById(R.id.song_Audio_Check_TV);                       // Do not DELETE. Needed for the 'DataModel.java' class. \\
    stopWatch = (Chronometer) findViewById(R.id.recorder_Chrono_CM);                      // Do not DELETE. Needed for the 'Audio Guide' recorder. \\
    audioGuidePBarFill = (TextView) findViewById(R.id.audio_Guide_PBar_Fill_TV);          // Do not DELETE. Needed for the 'Audio Guide' recorder. \\
    audioGuideFilePath = (TextView) findViewById(R.id.audio_Guide_File_Path_TV);          // Do not DELETE. Needed for the 'Audio Guide' recorder. \\
    recordAudioGuidePB = (ProgressBar) findViewById(R.id.audio_Guide_Create_PB);          // Do not DELETE. Needed for the 'DataModel.java' class. \\
    audioGuideDuration = (TextView) findViewById(R.id.recorded_Audio_Guide_Duration_TV);  // Do not DELETE. Needed for the 'Audio Guide' recorder. \\

    songIntroChords = (TextView) findViewById(R.id.song_Intro_Input_TV);                  // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songVerseChords = (TextView) findViewById(R.id.song_Verse_Input_TV);                  // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songChorusChords = (TextView) findViewById(R.id.song_Chorus_Input_TV);                // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songBridgeChords = (TextView) findViewById(R.id.song_Bridge_Input_TV);                // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songOutroChords = (TextView) findViewById(R.id.song_Outro_Input_TV);                  // Do not DELETE. Needed for the 'DataModel.java' class. \\

    songStructure = (TextView) findViewById(R.id.song_Structure_Input_TV);                // Do not DELETE. Needed for the 'DataModel.java' class. \\
    songStructure.setOnClickListener(this);

    startRecordBtn = (Button) findViewById(R.id.start_Audio_Record_BTN);
    startRecordBtn.setOnClickListener(this);

    stopRecordBtn = (Button) findViewById(R.id.stop_Audio_Record_BTN);
    stopRecordBtn.setOnClickListener(this);

    startPlaybackBtn = (Button) findViewById(R.id.start_Audio_Play_BTN);
    startPlaybackBtn.setOnClickListener(this);

    stopPlaybackBtn = (Button) findViewById(R.id.stop_Audio_Play_BTN);
    stopPlaybackBtn.setOnClickListener(this);

    deleteAudioBtn = (Button) findViewById(R.id.delete_Audio_Guide_BTN);
    deleteAudioBtn.setOnClickListener(this);

    defineChordsBtn = (Button) findViewById(R.id.define_Song_Chords_BTN);
    defineChordsBtn.setOnClickListener(this);

    goToReviewBtn = (Button) findViewById(R.id.review_Song_BTN);
    goToReviewBtn.setOnClickListener(this);

    exitToMainBtn = (Button) findViewById(R.id.review_Close_Song_BTN);
    exitToMainBtn.setOnClickListener(this);

    // Deactivate all the buttons in this view by using the 'SsbAtt' class to set 'Alpha' and 'Enable' fields. \\
    btnAttributes.oneButtonSetAlpha35(startPlaybackBtn);
    btnAttributes.oneButtonSetAlpha35(deleteAudioBtn);

    // Set the Visibility of the 'Start Audio Play' button to 'GONE'. \\
    stopRecordBtn.setVisibility(View.GONE);
    stopPlaybackBtn.setVisibility(View.GONE);

    // Set the 'Audio Guide Progress Bar' length to 2 minutes (i.e. 120 000 milliseconds). \\
    recordAudioGuidePB.setMax(120000);


    // Create the main folder on the devices external storage (if available) for storing NB Song Scrapbook data. \\
    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) // Check if SD card is mounted. \\
    {

        // Set up a reference to the directories you want to create for access by or via this Activity - for saving data to or retrieving data from. \\
        File ssAudioPath = new File(Environment.getExternalStorageDirectory() + "/Song Scrapbook/Audio Guides");

        if(!(ssAudioPath).exists()) {  // If the directory linked to 'ssAudioPath' already exits, do nothing and simply use that as the destination folder. \\
            ssAudioPath.mkdirs();      // If the directory linked to 'ssAudioPath' does not already exit...then create the directory. \\
        } else;


    } else;

     // ---------------------------------------------------------------- Data Fetching Section - START --------------------------------------------------------------------- \\

    /** Check to see if any data was passed from the previous Activity...if TRUE, then extract all data from the data bundle received **/
    if(getIntent().getExtras() != null) { // Check to see if there is any data in the default Activity Data Object. \\

        // Create a new bundle object and add to it the data passed from the previous activity...
        Bundle dataIn = getIntent().getExtras();

        // Update the relevant UI fields with the data passed from the previous activity...
        dataModel.importBpcData(dataIn, songTitle, songDate, songStructure, songIntroChords, songVerseChords, songChorusChords, songBridgeChords, songOutroChords, songLyrics, audioCheck, audioGuideDuration, audioGuidePBarFill, audioGuideFilePath);
    } else;

   // ---------------------------------------------------------------- Data Fetching Section - END ----------------------------------------------------------------------- \\

    if(audioCheck.getText().length() == 3) {

        // [1] Set the file path of the 'Audio Guide' linked to this song entry. \\
        agFileName = (String) audioGuideFilePath.getText();

        // [2] Update the 'Audio Guide' Record ProgressBar status. \\
        String getPbarFill = (String) audioGuidePBarFill.getText();
        recordAudioGuidePB.setProgress(Integer.parseInt(getPbarFill));

        // [3] Activate the 'Playback' and 'Delete' buttons. \\
        btnAttributes.oneButtonSetAlpha100(deleteAudioBtn);
        btnAttributes.oneButtonSetAlpha100(startPlaybackBtn);

        // [4] Deactivate the 'Audio Record' buttons. \\
        btnAttributes.oneButtonSetAlpha35(startRecordBtn);

        // Toast tst = Toast.makeText(this, "Value:  " + getPbarFill, Toast.LENGTH_SHORT);
        // tst.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
        // tst.show();
    } else;
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    if (!scalingComplete) // only do this once!!
    {
        newScaler.scaleContents(findViewById(R.id.songCreationContents), findViewById(R.id.songCreationContainer));
        scalingComplete = true;
    }
    super.onWindowFocusChanged(hasFocus);
}

// Called when the views have been created. We override this in order to scale the UI, which we can't do before this.
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    View view = super.onCreateView(name, context, attrs);
    return view;
}


// ----------------------------------------------------------- Audio Guide RECORD, Play and Delete Code START ------------------------------------------------------------- \\

long elapsedTimeBeforeStop;
private MediaPlayer mPlayer = null;
private MediaRecorder mRecorder = null;
private static String agFileName = null;


private final int TIMER_TICK = 1000;                        // Tells the TIMER to fire/tick ONCE every SECOND, decrease this to fire more frequently. \\
Timer progressBarAdvancer;
CountDownTimer recordingCountDown;
private static final String LOG_TAG = "AudioRecordTest";

// Needed for updating the recording 'Audio Guide' progress. \\
int countUp;
private Chronometer stopWatch = null;                       // Initialize a chronometer for count the time lapsed. \\

private int startCounter () {

    stopWatch.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
        @Override
        public void onChronometerTick(Chronometer chrono) {
            countUp = (int) ((SystemClock.elapsedRealtime() - chrono.getBase()) / 1000);
            int minutes = (countUp / 60);
            int seconds = (countUp % 60);
            audioGuideDuration.setText(String.format("%d:%02d", minutes, seconds));
        }
    });

    // Quickly reset the 'Counter' before starting it up again. This will ensure a clean start time everytime. \\
    resetCounter();

    // Start counting the time elapsed. \\
    stopWatch.start();

    // Start the updating of the Audio Guide recording progress bar. \\
    updateAudioRecordProgress();

    // Serve the 'countUp' object while the timing is in progress. \\
    return countUp;
}

private void startRecordingCountDownTimer() {

    recordingCountDown = new CountDownTimer(121000, 1000) {

        public void onTick(long millisUntilFinished) {
            // mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
        }

        public void onFinish() {
            // mTextField.setText("done!");
            stopRecording();
        }
    }.start();
}

private long stopCounter () {

    stopWatch.stop();

    // Get an immediate reference to the current 'SystemClock' time, and log that into the 'elapsedTimeBeforeStop' time object. \\
    long elapsedTimeBeforeStop = SystemClock.elapsedRealtime() - stopWatch.getBase();
    return elapsedTimeBeforeStop;
}

private void stopRecordingCountDownTimer() {

    // [1] Stop the 'recordingCountDown' counter. \\
    recordingCountDown.cancel();
}

private void resetCounter () {

    // Reset the 'stopWatch' to get a new start time. \\
    stopWatch.setBase(SystemClock.elapsedRealtime() - elapsedTimeBeforeStop);
}

public void createNewAudioID() {

    // Check if the 'audioGuideFilePath' hasn't already been defined and create a new file path if not already defined. \\
    if(audioGuideFilePath.getText() == "") {

        // [1] Create an ID for the 'Audio Guide' using the 'Song Title' of the song. \\
        String songTitleWowSpace = songTitle.getText().toString().replace(" ", "");
        String songIDPart1 = songTitleWowSpace.substring(0, 3);   // Splice 1 - Take the first 3 characters of the 'Song Title' string. \\
        String songIDPart2 = songTitleWowSpace.substring(songTitleWowSpace.length() - 3, songTitleWowSpace.length());  // Splice 2 -  Take the last 3 characters of the 'Somg Title' string. \\
        String songIDPart3 = songTitleWowSpace.substring(songTitleWowSpace.length()-3, songTitleWowSpace.length()-2);  // Splice 3 - Take the 3rd last character of the 'Song Title' string. \\
        String songID = songIDPart1 + songIDPart3 + songIDPart2 + ".3gp";  // Stitch all splices (i.e. 1, 2 & 3) together to create a new UNIQUE 'Song ID' string for the 'Audio Guide'. \\

        // [2] Get a reference to the 'Audio Guide' directory for saving the audio recording to. \\
        agFileName = Environment.getExternalStorageDirectory() + "/Song Scrapbook/Audio Guides";
        agFileName += "/" + songID;

        // [3] Set the 'audioGuideFilePath' value to that of the 'agFileName' string object. \\
        audioGuideFilePath.setText(agFileName);

        /**Toast tst = Toast.makeText(this, "Created:  " + agFileName, Toast.LENGTH_SHORT);
        tst.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
        tst.show(); **/
    } else;
}

private void getSongCreationDate() {

    // [1] Get an instance to the System Calendar, extract current date and insert it into the 'currDate' string object. \\
    Calendar cal = Calendar.getInstance();

    // [2] Define a date format, apply it to the 'currDate' string and insert it into another string object (i.e. ''). \\
    SimpleDateFormat dateForm = new SimpleDateFormat("dd-MMM-yy");
    String songCreationDate = dateForm.format(cal.getTime());

    // [3] Set the value/text of the 'songDate' to the newly created 'songCreationDate' string result. \\
    songDate.setText(songCreationDate);

    /** Toast tst = Toast.makeText(this, "Created:  " + songCreationDate, Toast.LENGTH_SHORT);
    tst.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
    tst.show(); **/
}

public void startRecording() {

    createNewAudioID();

    // Create a new Media Recorder and get the recording process in motion. \\
    mRecorder = new MediaRecorder();
    mRecorder.setMaxDuration(120000);
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    mRecorder.setOutputFile(agFileName);

    try {
        mRecorder.prepare();
    }

    catch (IOException e) {
        Log.e(LOG_TAG, "prepare() failed");
    }

    // Start audio recording. \\
    mRecorder.start();

    // Start the clock to time the duration of the recording. \\
    startCounter();

    // Start the countdown to make sure recording doesn't exceed 2 minutes. \\
    startRecordingCountDownTimer();
}

public void stopRecording() {

    // Stop the audio recorder timer. \\
    stopCounter();

    // Stop and clean the 'Audio Guide' progressbar updating process. \\
    progressBarAdvancer.cancel();
    progressBarAdvancer.purge();

    // Stop the recorder CountDownTimer. \\
    stopRecordingCountDownTimer();

    mRecorder.stop();
    mRecorder.release();
    mRecorder = null;

    // [1] Make the 'stopRecordBtn' button invisible and the 'startRecordBtn' button visible. \\
    startRecordBtn.setVisibility(View.VISIBLE);                                                  // Set visibility to GONE. \\
    stopRecordBtn.setVisibility(View.GONE);                                                      // Set visibility to VISIBLE. \\

    // [2] Re-enable ALL other views to prevent interruption of the current Audio Process. \\
    songTitle.setEnabled(true);
    songLyrics.setEnabled(true);
    goToReviewBtn.setEnabled(true);
    exitToMainBtn.setEnabled(true);
    songStructure.setEnabled(true);
    defineChordsBtn.setEnabled(true);

    // [3] Deactivate the 'Audio Record' button. \\
    btnAttributes.oneButtonSetAlpha35(startRecordBtn);

    // [4] Activate the following buttons. \\
    btnAttributes.oneButtonSetAlpha100(startPlaybackBtn);
    btnAttributes.oneButtonSetAlpha100(deleteAudioBtn);
    btnAttributes.oneButtonSetAlpha100(goToReviewBtn);
    btnAttributes.oneButtonSetAlpha100(exitToMainBtn);

    // [5] Insert the 'Yes' text into the 'audioCheK' TextView. \\
    audioCheck.setText("Yes");
}

public void startPlaying() {

    mPlayer = new MediaPlayer();

    try {
        mPlayer.setDataSource(agFileName);
        mPlayer.prepare();
        mPlayer.start();
    }

    catch (IOException e) {
        Log.e(LOG_TAG, "prepare() failed");
    }
}

public void stopPlaying() {

    mPlayer.release();
    mPlayer = null;
}

public void deleteAudioGuide() {

    // [1] Create a new File object and delete the value inserted into it by the 'createNewAudioID()' function. \\
    File thisAG = new File(agFileName);
    thisAG.delete();

    // [2] Clear the 'Audio Guide' progress bar. \\
    recordAudioGuidePB.setProgress(0);

    // [3] Reset the 'stopWatch' to get a new start time. \\
    resetCounter();

    // [4] Clear the 'Audio Guide' recording duration time. \\
    audioGuideDuration.setText("0:00");

    // [5] Insert the 'No' text into the 'audioCheK' TextView. \\
    audioCheck.setText("No");
}

public void updateAudioRecordProgress() {

    progressBarAdvancer = new Timer();

    progressBarAdvancer.scheduleAtFixedRate(new TimerTask() {

        public void run() {

            // [1] Run the timer for every 1000 milliseconds = 1 second. \\
            int runProgress = recordAudioGuidePB.getProgress() + TIMER_TICK;

            recordAudioGuidePB.setProgress(runProgress);
        }
    },
            1000, // Delay before first execution
            TIMER_TICK);
}

// ------------------------------------------------------------ Audio Guide RECORD, Play and Delete Code END -------------------------------------------------------------- \\


@Override
public void onClick (View v) {

    if (v.getId() == R.id.song_Structure_Input_TV) {

        // Create a bundle object. \\
        Bundle dataKeeper = new Bundle();

        // Get the NB data and pass it to the next Activity. \\
        dataModel.exportBpcData(dataKeeper, songTitle, songDate, songStructure, songIntroChords, songVerseChords, songChorusChords, songBridgeChords, songOutroChords, songLyrics, audioCheck, audioGuideDuration, recordAudioGuidePB, audioGuideFilePath);

        // Start new intent to move from the current activity to the next activity...
        Intent Bpc2SS = new Intent(BpcAct.this, SongStruct.class);
        Bpc2SS.putExtras(dataKeeper);
        startActivity(Bpc2SS);
    }

    else if (v.getId() == R.id.define_Song_Chords_BTN) {

        // Create a bundle object. \\
        Bundle dataKeeper = new Bundle();

        // Get the NB data and pass it to the next Activity. \\
        dataModel.exportBpcData(dataKeeper, songTitle, songDate, songStructure, songIntroChords, songVerseChords, songChorusChords, songBridgeChords, songOutroChords, songLyrics, audioCheck, audioGuideDuration, recordAudioGuidePB, audioGuideFilePath);

        // Start new intent to move from the current activity to the next activity...
        Intent Bpc2SC = new Intent (BpcAct.this, SongChords.class);
        Bpc2SC.putExtras(dataKeeper);
        startActivity(Bpc2SC);
    }

    else if (v.getId() == R.id.start_Audio_Record_BTN) {

        if (songTitle.length() == 0) {   // Check to see if the 'Song Title' EditText is empty. \\

            // If the 'Song Title' is empty, then show a warning message to the user. \\
            Toast tost = Toast.makeText(this, "Please create a  Song Title  first.", Toast.LENGTH_SHORT);
            tost.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
            tost.show();
        }

        else if (songTitle.length() <= 3) {   // Check to see if the 'Song Title' EditText is shorter than 3 characters. \\

            // If the 'Song Title' is empty, then show a warning message to the user. \\
            Toast tost = Toast.makeText(this, "The  Song Title  must be longer than 3 characters.", Toast.LENGTH_SHORT);
            tost.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
            tost.show();
        }

        else if (songTitle.length() > 3) {   // Check to see if the 'Song Title' EditText is longer than 3 characters. \\

            // [1] Start the recording the 'Audio Guide' file for the current song. \\
            startRecording();
        }
    }

    else if (v.getId() == R.id.stop_Audio_Record_BTN) {

        // [1] Deactivate the 'Audio Record' button. \\
        btnAttributes.oneButtonSetAlpha35(startRecordBtn);

        // [2] Activate the following buttons. \\
        btnAttributes.oneButtonSetAlpha100(startPlaybackBtn);
        btnAttributes.oneButtonSetAlpha100(deleteAudioBtn);
        btnAttributes.oneButtonSetAlpha100(goToReviewBtn);
        btnAttributes.oneButtonSetAlpha100(exitToMainBtn);

        // [3] Stop the recording the 'Audio Guide' file for the current song. \\
        stopRecording();
    }

    else if (v.getId() == R.id.start_Audio_Play_BTN) {

        // [1] Start playback of the 'Audio Guide' file for the current song. \\
        startPlaying();

        // [2] Make the 'stopRecordBtn' button visible and make the 'startRecordBtn' button invisible. \\
        stopPlaybackBtn.setVisibility(View.VISIBLE);
        startPlaybackBtn.setVisibility(View.INVISIBLE);

        // [3] Deactivate the 'DELETE Audio Guide' button. \\
        btnAttributes.oneButtonSetAlpha35(deleteAudioBtn);
    }

    else if (v.getId() == R.id.stop_Audio_Play_BTN) {

        // [1] Stop playback of the 'Audio Guide' file for the current song. \\
        stopPlaying();

        // [2] Make the 'stopRecordBtn' button visible and make the 'startRecordBtn' button invisible. \\
        startPlaybackBtn.setVisibility(View.VISIBLE);
        stopPlaybackBtn.setVisibility(View.GONE);

        // [3] Reactivate the 'DELETE Audio Guide' button. \\
        btnAttributes.oneButtonSetAlpha100(deleteAudioBtn);
    }

    else if (v.getId() == R.id.delete_Audio_Guide_BTN) {

        // [1] Delete the relevant 'Audio Guide' file from the storage folder. \\
        deleteAudioGuide();

        // [2] Re-Activate the 'Record Audio' button. \\
        btnAttributes.oneButtonSetAlpha100(startRecordBtn);

        // [3] Deactivate the 'Delete Audio Guide' and 'Play Audio Guide' buttons. \\
        btnAttributes.oneButtonSetAlpha35(deleteAudioBtn);
        btnAttributes.oneButtonSetAlpha35(startPlaybackBtn);
    }

    else if (v.getId() == R.id.review_Song_BTN) {

        // [1] Check if the 'getSongCreationDate' object is empty and insert the current date into the object. \\
        if(songDate.getText().length() == 0) {
            // Create a new song creation date (i.e. insert current date) by executing the 'getSongCreationDate()' function. \\
            getSongCreationDate();
        }else;

        // [2] Create a bundle object...
        Bundle dataKeeper = new Bundle();

        // [3] Get the NB data and pass it to the next Activity. \\
        dataModel.exportBpcData(dataKeeper, songTitle, songDate, songStructure, songIntroChords, songVerseChords, songChorusChords, songBridgeChords, songOutroChords, songLyrics, audioCheck, audioGuideDuration, recordAudioGuidePB, audioGuideFilePath);

        // [4] Start new intent to move from the current activity to the next activity. \\
        Intent bpc2bpr = new Intent (BpcAct.this, BprAct.class);
        bpc2bpr.putExtras(dataKeeper);
        startActivity(bpc2bpr);
        overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out);
    }

    else if (v.getId() == R.id.review_Close_Song_BTN) {

        Intent bpc2main = new Intent (BpcAct.this, MainAct.class);
        bpc2main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(bpc2main);
        overridePendingTransition(R.anim.slide_right_out, R.anim.slide_left_in);
    }
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    overridePendingTransition(R.anim.slide_right_out, R.anim.slide_left_in);
}
}

I have been struggling with this for a while now and I really don't know where the problem could be. The odd things that I have two physical devices (Galaxy Mega 6.3 and Galaxy X-Cover 2) on which I test the application every now and then. The application seems to run fine on the Mega 6.3 (which runs Android 4.2.2), but crashes every time when I run it on the X-cover 2 (which is running Android 4.1.2). Note problem also only happens when I hit the audio record button. Any help will be much appreciated.

Was it helpful?

Solution

 private void startRecord(){

      File file = new File(Environment.getExternalStorageDirectory(), "test.pcm"); 

      try {
       file.createNewFile();
       recording=true;
       OutputStream outputStream = new FileOutputStream(file);
       BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
       DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);

       int minBufferSize = AudioRecord.getMinBufferSize(44100, 
         AudioFormat.CHANNEL_IN_MONO, 
         AudioFormat.ENCODING_PCM_16BIT);

       short[] audioData = new short[minBufferSize];

       AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
         44100,
         AudioFormat.CHANNEL_IN_MONO,
         AudioFormat.ENCODING_PCM_16BIT,
         minBufferSize);
       //int sessionId=audioRecord.getAudioSessionId();
     //  NoiseSuppressor.create(sessionId);
       audioRecord.startRecording();

       while(recording){
        int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
        for(int i = 0; i < numberOfShort; i++){
         dataOutputStream.writeShort(audioData[i]);
        }
       }

       audioRecord.stop();
       dataOutputStream.close();

      } catch (IOException e) {
       e.printStackTrace();
      }

     }

here by using this function raw data of recording(PCM) will be saved in external directory. you should play this recording by using AudioTrack object.

OTHER TIPS

I am not sure what is wrong with the mRecorder, but I usually use an AudioRecord object for recording audio rather then the full blown MediaRecorder which can potentially do a lot more then just record audio. Either way check out the android dev page for AudioRecord http://developer.android.com/reference/android/media/AudioRecord.html hope that helps.

P.S. found this graph on the states of the media recorder http://developer.android.com/images/mediarecorder_state_diagram.gif if you don't like the AudioRecord this chart may be able to help you debug where you MediaRecorder is getting put in an invalid state

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top