Android : MediaPlayer getDuration() and getCurrentPosition() has NullPointerException

21,222

Solution 1

Your problem area is here:

play.execute();
recordingDuration[0] =play.getDuration();

There is no guarantee when the AsyncTask will finish after doing play.execute(), because this is a Thread and has its own life. Therefore your MediaPlayer may not have been initialized by then. Try do the part:

recordingDuration[0] =play.getDuration();
seekBar.setMax(recordingDuration[0]);

After your AsyncTask completes the background job. This should be done in your PostExecute method and will resolve the Exception.

But after a bit of thought, let's realize that the design is wrong. You don't need to maintain a MediaPlayer in an AsyncTask.

Create and manage the MediaPlayer in your Activity. Make your Activity implement OnPreparedListener. Get the duration and set the seekbar via onPrepared(check the sample code below). You can get duration only when file is loaded and your player is ready.

Move the Pause and Resume methods to your Activity. AsyncTask is primarily used to get long running tasks done. I have put an example code below which should help to understand the point.

public class MainActivity implements MediaPlayer.OnPreparedListener{

       private MediaPlayer mediaPlayer;
       boolean isReady;
       boolean paused;

       .....
       button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Your logic to play, pause and initialize if needed
            if (!MainActivity.filepath.equals("Nothing")) {
               if(mediaPlayer != null && mediaPlayer.isPlaying()){
                    pause();
                    paused = true;
               }else if(paused){
                    resume();
                    paused = false;
               }
               // initialize again when player is stopped and another file is set
               // in that case put logic so that mediaPlayer is disposed and set to null 
               if (mediaPlayer == null){
                    initializeMediaPlayer();
               }


            }
        }
    });

    public void initializeMediaPlayer(){
            mediaPlayer = new MediaPlayer();
            try {
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath().toString()+"/Notate/"+MainActivity.filepath+".wav");
                mediaPlayer.setOnPreparedListener(this);
                mediaPlayer.prepareAsync(); // this is important so that UI is not stuck
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {

            }
    }

    // You need to listen for when the Media Player is finished preparing and is ready
    @Override
    public void onPrepared(MediaPlayer mp) {

        recordingDuration[0] = mediaPlayer.getDuration();

        //Called when the media file is ready for playback.
        isReady = true;
        // Start the player
        mediaPlayer.start();

    }

    public void pause(){

        if (mediaPlayer != null){
            mediaPlayer.pause();
            length=mediaPlayer.getCurrentPosition();
        }
    }
    public void resume(){

        if (mediaPlayer != null){
            mediaPlayer.seekTo(length);
            mediaPlayer.start();
        }
    }

   @Override
   public void onDestroy() {
       if (mediaPlayer != null) mediaPlayer.release();
   }


}

Solution 2

Get Current Possition Java Code:

mediaPlayer.getCurrentPosition();

Get Duration Java Code:

 private int getAudioDuration() {
    FFmpegMediaMetadataRetriever fFmpegMediaMetadataRetriever = new FFmpegMediaMetadataRetriever();
    fFmpegMediaMetadataRetriever.setDataSource(MP3);
    fFmpegMediaMetadataRetriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ALBUM);
    fFmpegMediaMetadataRetriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ARTIST);
    int duration = Integer.parseInt(fFmpegMediaMetadataRetriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
    Log.v(TAG, "getDuration= " + duration);
    fFmpegMediaMetadataRetriever.release();
    return duration;
}

Build.Gradle(:app)

dependencies {
    implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-core:1.0.15'
    implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-native:1.0.15'
}
Share:
21,222
shivram
Author by

shivram

Updated on July 09, 2022

Comments

  • shivram
    shivram almost 2 years

    Creating a MediaPlayer. The particular class has the functions to play, pause and resume. I am trying to make a SeekBar which will display the progress. SeekBar requires as the value of the maxlength which is to be obtained from the getDuration() function which calls the mediaplayer.getDuration() function and returns the value. SeekBar also requires the value of the current position which is obtained from the getCurrentPostion() function. Both of them are returning a NullPointerException.

    public class PlayMedia extends AsyncTask<Void, Void, Void>
        implements MediaPlayer.OnPreparedListener {
    
    
    private MediaPlayer mediaPlayer;
    int length;
    int duration =0;
    int currentPosition=0;
    @Override
    protected Void doInBackground(Void... params) {
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath().toString()+"/Notate/"+MainActivity.filepath+".wav");
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.prepareAsync();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
    
        }
        return null;
    }
    
    @Override
    protected void onPostExecute(Void result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
    
       }
    public int getDuration(){
        duration=mediaPlayer.getDuration();
        Log.d("Position",Integer.toString(duration));
        return duration;
    }
    public int getPresentDuration(){
        currentPosition=mediaPlayer.getCurrentPosition();
        Log.d("CurrentPosition",Integer.toString(currentPosition));
        return currentPosition;
    }
    
    @Override
    public void onPrepared(MediaPlayer mp) {
        // TODO Auto-generated method stub
        if(mediaPlayer != null && mediaPlayer.isPlaying()){
            mediaPlayer.pause();
        }
        else if(mediaPlayer != null){
        mediaPlayer.start();
            }
        Log.d("Shivram", "Started Playing");
    
    }
    public void pause(){
        mediaPlayer.pause();
        length=mediaPlayer.getCurrentPosition();
        Log.d("Shivram","Paused");
    }
    public void resume(){
        mediaPlayer.seekTo(length);
        mediaPlayer.start();
        Log.d("Shivram","Resume");
    

    This Fragment Class calls the getDuration() function, where the exception is created.

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        contentViewC = inflater.inflate(R.layout.fragment_fragment_b, container, false);
        final SeekBar seekBar;
    
        Button button = (Button) contentViewC.findViewById(R.id.button1);
        Button button2 = (Button) contentViewC.findViewById(R.id.button2);
    
        textToChange=(TextView)contentViewC.findViewById(R.id.textView1);
        final PlayMedia play=new PlayMedia();
        boolean pause=false;
        seekBar = (SeekBar) contentViewC.findViewById(R.id.SeekBar01);
        final int[] recordingDuration = new int[1];
    
    
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (MainActivity.filepath != "Nothing") {
                    if(play.getStatus()==AsyncTask.Status.FINISHED || play.getStatus()==AsyncTask.Status.RUNNING){
                        Log.d("Shivram-FragmentA", "Resume");
                        play.resume();
    
                    }
                    if(play.getStatus()==AsyncTask.Status.PENDING) {
                        play.execute();
                        recordingDuration[0] =play.getDuration();
                        seekBar.setMax(recordingDuration[0]);
                    }
                    Frequency getFreq=new Frequency();
    
                  getFreq.execute();
                }
            }
        });
    

    The stackTrace is as follows

    01-13 21:44:15.182  16263-16263/com.example.shivram.notate E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.shivram.notate, PID: 16263
    java.lang.NullPointerException
            at com.example.shivram.notate.PlayMedia.getDuration(PlayMedia.java:43)
            at com.example.shivram.notate.FragmentC$1.onClick(FragmentC.java:66)
            at android.view.View.performClick(View.java:4456)
            at android.view.View$PerformClick.run(View.java:18465)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5086)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)