Search code examples
javaandroideclipseandroid-mediaplayerandroid-mediarecorder

Can't play the recorded file


I'm making an app that records audio as long as the imagebutton is touched and held. I achieved this with the following code:

public class MainActivity extends Activity {

MediaRecorder recorder;
MediaPlayer mediaPlayer;

//STORAGE PATHS
String storagePath;
String externalStoragePath;

//FULL OUTPUT PATHS
String externalOutputPath;

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

    //AUDIO RECORDER
    recorder = new MediaRecorder();
    recorder.reset();       
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
    {
        externalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
        externalOutputPath = externalStoragePath + File.separator + "/Android/data/com.whizzappseasyvoicenotepad/test.mp3";
        recorder.setOutputFile(externalOutputPath);
    }
    else
    {
        storagePath = Environment.getDataDirectory().getAbsolutePath();
        recorder.setOutputFile(storagePath + "/Android/data/com.whizzappseasyvoicenotepad/test.mp3");
    }

    //IMAGE BUTTON ONTOUCHLISTENER
    final ImageButton recBtn = (ImageButton) findViewById(R.id.recButton);
    recBtn.setOnTouchListener(new OnTouchListener(){

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_DOWN)
            {
                recBtn.setImageResource(R.drawable.record_btn_pressed);
                try {
                    recorder.prepare();
                    recorder.start();
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            else if (event.getAction() == MotionEvent.ACTION_UP)
            {
                recBtn.setImageResource(R.drawable.record_btn);
                try {
                    recorder.prepare();
                    recorder.stop();
                    recorder.reset();
                    recorder.release();
                    recorder = null;
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Log.i(STORAGE_SERVICE, "File saved to: " + externalStoragePath + "/Android/data/com.whizzappseasyvoicenotepad/test.3gp");
            }
            return true;
        }

    });
} //END OF ONCREATE

Now after I've stopped recording, I searched for the mp3 file in file manager (android app) and tried playing it music player but it doesn't work. It says that the file can't be played.

I then also tried to add a "test play" button to the app, to try and play the recorded file with MediaPlayer but it doesn't work either. As soon as I press the play button, the app crashes.

public void testPlay (View v) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException{
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setDataSource(externalOutputPath);
    mediaPlayer.start();
}

Yes, I did add android:onClick="testPlay" to the xml file

Logcat file:

07-31 16:51:43.938: E/MediaPlayer(26918): Unable to to create media player
07-31 16:51:43.953: E/AndroidRuntime(26918): FATAL EXCEPTION: main
07-31 16:51:43.953: E/AndroidRuntime(26918): java.lang.IllegalStateException: Could not execute method of the activity
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.view.View$1.onClick(View.java:3633)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.view.View.performClick(View.java:4240)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.view.View$PerformClick.run(View.java:17721)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.os.Handler.handleCallback(Handler.java:730)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.os.Handler.dispatchMessage(Handler.java:92)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.os.Looper.loop(Looper.java:137)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.app.ActivityThread.main(ActivityThread.java:5103)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at java.lang.reflect.Method.invokeNative(Native Method)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at java.lang.reflect.Method.invoke(Method.java:525)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at dalvik.system.NativeStart.main(Native Method)
07-31 16:51:43.953: E/AndroidRuntime(26918): Caused by: java.lang.reflect.InvocationTargetException
07-31 16:51:43.953: E/AndroidRuntime(26918):    at java.lang.reflect.Method.invokeNative(Native Method)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at java.lang.reflect.Method.invoke(Method.java:525)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.view.View$1.onClick(View.java:3628)
07-31 16:51:43.953: E/AndroidRuntime(26918):    ... 11 more
07-31 16:51:43.953: E/AndroidRuntime(26918): Caused by: java.io.IOException: setDataSourceFD failed.: status=0x80000000
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.media.MediaPlayer.setDataSource(Native Method)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.media.MediaPlayer.setDataSource(MediaPlayer.java:981)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.media.MediaPlayer.setDataSource(MediaPlayer.java:960)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at android.media.MediaPlayer.setDataSource(MediaPlayer.java:918)
07-31 16:51:43.953: E/AndroidRuntime(26918):    at com.whizzappseasyvoicenotepad.MainActivity.testPlay(MainActivity.java:99)
07-31 16:51:43.953: E/AndroidRuntime(26918):    ... 14 more

Permissions:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Solution

  • I'm still not sure what was the problem, but I think there was something wrong with the way I stopped recording (the whole try, catch thing). I just rewrote the whole code and put the MediaRecorder in two different methods. startRecording() and stopRecording() method. And now it works perfectly!

    startRecording()

    public void startRecording (){
         recorder = new MediaRecorder();
         recorder.reset();      
         recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
         recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
         recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
         if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
         {
             externalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
             externalOutputPath = externalStoragePath + File.separator + "/Android/data/com.whizzappseasyvoicenotepad/test.mp3";
             recorder.setOutputFile(externalOutputPath);
         }
         else
         {
            storagePath = Environment.getDataDirectory().getAbsolutePath();
            recorder.setOutputFile(storagePath + "/Android/data/com.whizzappseasyvoicenotepad/test.mp3");
         }
         recorder.setOnErrorListener(errorListener);
         recorder.setOnInfoListener(infoListener);
    
         try {
            recorder.prepare();
            recorder.start();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    stopRecording()

    public void stopRecording() {
        if (null != recorder) {
            recorder.stop();
            recorder.reset();
            recorder.release();
    
            recorder = null;
        }
    }