OnCompletionListener - 应用停止工作

时间:2014-07-17 14:00:29

标签: android media-player

我正在使用一种方法来初始化和准备一个MediaPlayer(定义为类变量)。它需要一个String作为参数的歌曲名称,它将DataSource设置为该特定路径。

public void create_and_prepare_song(String x) {
    if (mp != null)
        mp.release();
    mp = new MediaPlayer();
    String filePath = Environment.getExternalStorageDirectory().getPath() + "/songsfolder/" + x + ".mp3";

    try {
        mp.setDataSource(filePath);
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        mp.prepare();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

现在,在我的代码中的某处,我使用此方法初始化并准备“1.mp3”。然后,只要这首歌结束,我就使用onCompletionListener,以便播放“2.mp3”,然后播放“3.mp3”。我用:

create_and_prepare_song("1");
i = 2;
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
    if (i <= 3) {
        String int_to_String = i + "";
        create_and_prepare_song(int_to_String); //1
        mp.setOnCompletionListener(this);
        mp.start();
        i++;
        }    
    }
});
mp.start();

现在,这会导致应用停止工作!但是,如果我只是将方法的主体复制并粘贴到// 1行,那么应用程序可以正常工作,播放第一首,第二首和第三首歌曲。为什么会这样?非常感谢

2 个答案:

答案 0 :(得分:2)

请注意,您正在create_and_prepare_song()内创建一个新玩家,但旧的玩家仍会在侦听器内部被引用。

那是因为全局变量和onCompletion参数具有相同的名称:mp

这里有一段有用的代码:

package com.example.simon.mplaylist;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import java.io.IOException;

/**
 * Created by Simon on 2014 Jul 20.
 */

public class MainActivity extends Activity {

    static int currentSong;
    static MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (mediaPlayer != null)
            return;

        currentSong = 1;
        create_and_prepare_song(currentSong);

        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                if (currentSong++ >= 3) {
                    mediaPlayer = null;
                    return;
                }
                create_and_prepare_song(currentSong);
                mediaPlayer.setOnCompletionListener(this);
                mediaPlayer.start();
            }
        });
        mediaPlayer.start();

    }

    public void create_and_prepare_song(int songNum) {
        if (mediaPlayer != null)
            mediaPlayer.release();
        mediaPlayer = new MediaPlayer();

        String storage = Environment.getExternalStorageDirectory().getPath();
        String filePath = storage + "/songsfolder/" + String.valueOf(songNum) + ".mp3";

        try {
            mediaPlayer.setDataSource(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            mediaPlayer.prepare();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意我还将MediaPlayer定义为静态,并且还要检查@ onCreate是否存在。这样,如果重新创建活动(例如屏幕旋转),则可以避免一次播放多首歌曲。

答案 1 :(得分:0)

你真的不应该在create_and_prepare_song()内开始实际播放。它应该在onPrepared()内启动,因为从prepare()调用可能会有一些延迟,并且媒体已准备好播放。