7

How to set From and To Timestamp markers and play media between these two points of an audio file? I don't see listener API for MediaPlayer in Android. Wondering how I can go about achieving this?

My situation is like this: Break audio file into many such parts and let user interactively play/replay select portions of it as he wishes.

For instance, let's assume a small audio file is broken into 3 parts (A---B---C---D), namely, AB, BC, and CD. The user selects part BC and opts to play. The audio then plays starting from point B and stops when it reaches point C. The user may play again part BC or choose to move on to the next part.

While its easier to decide to figure out the starting point and use mediaPlayer.seekTo(int) API, how is it that I can make the audio stop at the end point? What is the best way forward for this?

Your help is much appreciated.

karthiks
  • 7,049
  • 7
  • 47
  • 62
  • I know that one way of achieving this is by using `Handler` and tracking `mediaPlayer.getCurrentPosition()` every sec to see if it has reached the target point? Is there a better way than this one? – karthiks Aug 30 '16 at 10:22

4 Answers4

4

I think you can use mediaPlayer.seekTo(int msec)

mediaPlayer.setLooping(true); 
mediaPlayer.seekTo(0); 
mediaPlayer.start(); 
Jame
  • 3,746
  • 6
  • 52
  • 101
  • 1
    In addition to @user8430 'th answer, to use `from`, use `seekTo`, and to use `to` use player's `onProgress` listener, and stop playback once it reaches required moment. – Vladyslav Matviienko Aug 30 '16 at 07:50
  • @VladMatvienko, there is no onProgress listener on mediaPlayer unfortunately :( – karthiks Aug 30 '16 at 10:19
  • @karthiks: Do you see this http://android-er.blogspot.kr/2012/06/seek-to-specified-time-position-with.html? I think it will be useful for you – Jame Aug 30 '16 at 10:23
  • @karthiks, you're right, I forgot there is no. But any moment you can check the progress, and stop playback. – Vladyslav Matviienko Aug 30 '16 at 12:01
4

I've used a timer to do something similar. The following code assumes you have a layout with one button (with id 'button') and your mp3 file is 'myMp.mp3' and it's present at the raw folder.
The play method gets two parameters, both in miliseconds - the start point and the duration, but you can easily change it to start and stop points.

private MediaPlayer mediaPlayer;
private Timer timer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btnStart = (Button) findViewById(R.id.button);
    mediaPlayer = MediaPlayer.create(this, R.raw.myMp);

    btnStart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            preparePlayer();
            play(20000, 3000);
        }
    });        
}

private void preparePlayer() {
    try {
        mediaPlayer.prepareAsync();
    } catch (Exception e) {
        //Handle exception
    }
}

private void play(int start, int duration) {
    mediaPlayer.seekTo(start);
    mediaPlayer.start();
    timer = new Timer();
    timer.schedule(new PlayerTask(), duration);
}

class PlayerTask extends TimerTask {

    @Override
    public void run() {
        mediaPlayer.stop();
    }
}    
TDG
  • 5,909
  • 3
  • 30
  • 51
  • I did try this. There is a bug in this code in that you can't update a UI from a `TimerTask` thread. – karthiks Sep 09 '16 at 18:39
  • I don't see that you've mentioned anything about updating the UI in your question, just that you want to play audio file between two points. There are many questions about UI updating in SO: http://stackoverflow.com/questions/4369537/update-ui-from-thread, http://stackoverflow.com/questions/5185015/updating-android-ui-using-threads and many more. – TDG Sep 09 '16 at 18:48
1

I think you can use Handler.sendMessageDelayed. Call that function when you start the mediaPlayer. Say you want to play for X seconds, you can pass X - 1 as the argument (-1 as the buffer). That's because we have to take different factors into consideration, message scheduling, mediaPlayer start delay, etc. When the message arrives you check getCurrentPosition. If there's time left, you check the position every few milliseconds.

If you don't need it to be precise, you can pass X directly and stop it once the message arrives.

suitianshi
  • 3,300
  • 1
  • 17
  • 34
1

The way I went about implementing this is as below:

private MediaPlayer mediaPlayer;
private Runnable runnable = new Runnable() {
    @Override
    public void run() {
        mediaPlayer.pause();
        playPauseButton.setText(R.string.play);
    }
};

private void play(int start, int duration) {
    mediaPlayer.seekTo(start);
    handler.postDelayed(runnable, duration);
}

I've copied the key portion of the code relevant for this context. While I did this, I'm not particularly happy with this implementation because this is still not accurate.

I was looking to see if there is someone who used an alternative API to achieve accuracy for this, may be by using Android's AudioTrack API or something like that.

Looks like this is the best alternative available for now, to the best of my knowledge. I shall update this post, should I find a better way and until then, I hope this serves you well as much as it has served me. Cheers!

karthiks
  • 7,049
  • 7
  • 47
  • 62