0

I am currently trying to record audio on long tap and hold. The application works when I tap and hold, however, the app crashes when I click the button instead. Please help me figure out why this is happening.

p/s: Also, can someone tell me how to format log to display here? I have hard time with that

Code

  public class MainActivity extends AppCompatActivity {

    private static final String LOG_TAG = "Hello";
    TextView recordDisplay;
    Button recordButton;
    private MediaRecorder mRecorder = null;
    private String mFileName = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recordDisplay = (TextView) findViewById(R.id.dislayRecordView);
        recordButton = (Button) findViewById(R.id.recordButton);
        mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
        mFileName += "/SKBeon_recording.3gp";

        recordButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if(motionEvent.getAction()==MotionEvent.ACTION_DOWN){
                    startRecording();
                    recordDisplay.setText("Recording Started!");
                }else if (motionEvent.getAction() == MotionEvent.ACTION_UP){
                    stopRecording();
                    recordDisplay.setText("Recording Sopped!");
                }
                return false;
            }
        });

    }

    private void startRecording() {
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

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

        mRecorder.start();
    }

    private void stopRecording() {
        mRecorder.stop();
        mRecorder.release();
        mRecorder = null;
    }
}

Xml main:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <TextView
        android:id="@+id/dislayRecordView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/recordButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Record"
         />

</LinearLayout>

LogCat:

- 09-04 01:28:51.618 22535-22535/english_malay.my.apps.com.recordaudio E/MediaRecorder: stop failed: -1007


- 09-04 01:28:51.619 22535-22535/english_malay.my.apps.com.recordaudio E/InputEventReceiver: Exception dispatching input event.
- 09-04 01:28:51.619 22535-22535/english_malay.my.apps.com.recordaudio E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
- 09-04 01:28:51.621 22535-22535/english_malay.my.apps.com.recordaudio E/MessageQueue-JNI: java.lang.RuntimeException: stop failed.

  * at android.media.MediaRecorder.stop(Native Method)

  * at english_malay.my.apps.com.recordaudio.MainActivity.stopRecording(MainActivity.java:70)


  * at english_malay.my.apps.com.recordaudio.MainActivity.access$100(MainActivity.java:18)


- 09-04 01:28:51.621 22535-22535/english_malay.my.apps.com.recordaudio D/AndroidRuntime: Shutting down VM


- 09-04 01:28:51.622 22535-22535/english_malay.my.apps.com.recordaudio E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                       - Process: english_malay.my.apps.com.recordaudio, PID: 22535
                                                                                     java.lang.RuntimeException: stop failed.


   * at android.media.MediaRecorder.stop(Native Method)



   * at english_malay.my.apps.com.recordaudio.MainActivity.stopRecording(MainActivity.java:70)
Atef Hares
  • 4,715
  • 3
  • 29
  • 61
S.k. Surain
  • 53
  • 10

4 Answers4

2

Simply it's because you are trying to stop non-recording recorder!

you should do checking before stopping the recorder.

  private void startRecording() {
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }
        isRecording = true;
        mRecorder.start();
    }

and :

private void stopRecording() {
      try{
       if(mRecorder!=null && isRecording){
         mRecorder.stop();
         mRecorder.release();
         mRecorder = null;
       }
     }catch (Exception e){//handle this exception} 
    }

Also you should add some delay period (1 sec for example) before starting the recording in when: action == MotionEvent.ACTION_DOWN, to be able to differentiate between click and click&hold

Atef Hares
  • 4,715
  • 3
  • 29
  • 61
  • Great, It works!. One last thing, can you tell me how to delay before start recording or any links will do as well. Thanks a bunch, Atef Hares. – S.k. Surain Sep 03 '17 at 18:27
  • @S.k.Surain you're welcome. you can use this [answer](https://stackoverflow.com/a/9166354/5993410) it's an easy way to delay executing some code. – Atef Hares Sep 03 '17 at 18:29
  • I am also curious. How does it not record since technically invokes Action_down (which in turn invokes startRecording())? Thank you again – S.k. Surain Sep 03 '17 at 18:31
  • yes, but `click` invoked both actions `down` then `up` which the period between both of them takes could take less than 50 ms and the recorder's prepare method do some stuff that might take some short period, so when executing `stop()` the recorder was not being prepared yet or was done and about to start recording but not yet actually started! – Atef Hares Sep 03 '17 at 18:36
  • 1
    That makes sense. I wish I could give you more upvotes. Thank you, Atef! – S.k. Surain Sep 03 '17 at 18:43
1

Wrap your stopRecording() content in try/catch statement

bukkojot
  • 1,526
  • 1
  • 11
  • 16
1

your mRecorder is null when call stopRecording. Make following changes

  private void stopRecording() {
    if(mRecorder!=null ){
            mRecorder.stop();
            mRecorder.release();
            mRecorder = null;
        }
}
akshay_shahane
  • 4,423
  • 2
  • 17
  • 30
1

You have to check if the mRecorder object is null before calling the stop() method on it. Since the object is null you are getting a crash.

private void stopRecording() {
        if(null != mRecorder){
            mRecorder.stop();
            mRecorder.release();
            mRecorder = null;
        }
}
Karan Sharma
  • 2,353
  • 4
  • 28
  • 46