在点A和点B之间播放音频。

7
如何设置音频文件的起始时间和结束时间,并在这两个时间点之间播放媒体?在Android中,我没有看到MediaPlayer的listener API。想知道如何实现?
我的情况是这样的:将音频文件分成多个部分,并让用户以交互方式播放/重新播放所选择的部分。
例如,假设一个小音频文件被分成3个部分(A---B---C---D),即AB、BC和CD。用户选择BC部分并选择播放。然后音频从B点开始播放,直到达到C点时停止。用户可以再次播放BC部分,或选择移动到下一部分。
虽然确定起始点并使用mediaPlayer.seekTo(int) API更容易,但如何使音频在终点停止呢?前进的最佳方法是什么?
感谢您的帮助。

我知道实现这个的一种方法是使用Handler并每秒跟踪mediaPlayer.getCurrentPosition()以查看是否已达到目标点?除此之外还有更好的方法吗? - karthiks
4个回答

4
我使用了一个计时器来做类似的事情。以下代码假定您有一个布局,其中包含一个按钮(id为“button”),您的mp3文件是“myMp.mp3”,并且它存在于raw文件夹中。
play方法接收两个参数,都是以毫秒为单位的时间点和持续时间,但您可以轻松地将其更改为开始和停止点。
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();
    }
}    

我尝试过这个。这段代码存在一个bug,就是不能从“TimerTask”线程更新用户界面。 - karthiks
我在你的问题中没有看到你提到任何关于更新UI的内容,只是想在两个点之间播放音频文件。在SO上有很多关于UI更新的问题:https://dev59.com/HG855IYBdhLWcg3wYjWF,https://dev59.com/w2435IYBdhLWcg3w1jyV等等。 - TDG

4

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

mediaPlayer.setLooping(true); 
mediaPlayer.seekTo(0); 
mediaPlayer.start(); 

1
除了@user8430的答案之外,要使用from,请使用seekTo,要使用to,请使用播放器的onProgress监听器,并在达到所需时刻后停止播放。 - Vladyslav Matviienko
@VladMatvienko,不幸的是mediaPlayer上没有onProgress监听器 :( - karthiks
@karthiks: 你看过这篇文章吗?http://android-er.blogspot.kr/2012/06/seek-to-specified-time-position-with.html 我认为它对你会有用。 - Jame
@karthiks,你是正确的,我忘记了这一点。但是你随时可以查看进度并停止播放。 - Vladyslav Matviienko

1
我认为你可以使用 Handler.sendMessageDelayed。在你 start mediaPlayer 时调用该函数。假设你想播放 X 秒,则可以将 X - 1 作为参数传递(-1 作为缓冲)。这是因为我们必须考虑不同的因素,如消息调度、mediaPlayer 启动延迟等。当消息到达时,您检查 getCurrentPosition。如果还有时间,您每隔几毫秒检查一次位置。
如果您不需要它精确,请直接传递 X 并在消息到达后停止它。

1
我实现这个的方法如下:

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);
}

我已复制与此上下文相关的代码关键部分。虽然我这样做了,但我对这种实现并不特别满意,因为这仍然不准确。
我想看看是否有人使用了另一种API来实现这个准确性,可能是通过使用Android的AudioTrack API或类似的东西。
据我所知,看起来这是目前最好的替代方法。如果我找到更好的方法,我会更新这篇文章,直到那时,我希望这能像它对我一样对你有用。干杯!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接