1

我正在实现一个游戏,我想使用一个且只有一个 MediaPlayer 实例,它在与 UI 不同的线程中运行。每个音频文件都被发送到一个 FIFO 队列,如果没有文件正在播放,或者队列中的前一个文件播放完,就会立即播放。我已经实现了一个单例类来支持这一点,如下所示:

public class ThePlayer {
private static ThePlayer instance = null;
private Context context;
Thread playerThread;
BlockingQueue<Integer> listIDs = new LinkedBlockingQueue<Integer>();
MediaPlayer player;
Integer playID; 

private ThePlayer() {
    player = null;
    playerThread = new Thread(new Runnable() {
        //Object locker = new Object();
        public void run() {
            while (true) {
                try {
                    playID = listIDs.take(); // blocks if list empty
                    Log.d(this.getClass().getName(), "Took ID 0x" + Integer.toHexString(playID));
                    player = MediaPlayer.create(context, playID); 
                    player.setOnCompletionListener(
                            new MediaPlayer.OnCompletionListener() {
                                public void onCompletion(MediaPlayer mp) {
                                        mp.release();
                                        mp = null;
                                        synchronized (playerThread) {
                                            Log.d(this.getClass().getName(), "Finished playing 0x"+Integer.toHexString(playID));
                                            playerThread.interrupt();
                                        }
                                }
                            });
                    player.start();
                    Log.d(this.getClass().getName(), "Started playing 0x"+Integer.toHexString(playID));
                    synchronized (this) {
                        Log.d(this.getClass().getName(), "Now wait to finish");
                        wait(); // until finished playing
                    }                       
                } catch (InterruptedException ie) {
                    Log.d(getClass().getName(), "Player thread wait interrupted");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    });
    playerThread.setName("PlayerThread");
    playerThread.start();
}


public static ThePlayer getInstance()
{
    if(instance == null)
    {
        instance = new ThePlayer();
    }
    return instance;
}

public void play(Context _ctx, int id) {
    context = _ctx;
    listIDs.add(id);
    Log.d(this.getClass().getName(), "Added ID 0x" + Integer.toHexString(id));
}

public void stop() {
    //TODO: implement
}

}

一般来说,这很好用,但一个特定的文件无法以不一致的方式播放。换句话说,在大多数情况下,它不播放,但偶尔会播放。所有日志条目都表明文件已排队,MediaPlayer 已分配并启动,并且 onCompletion 函数已被调用。绝不会抛出异常。这发生在摩托罗拉 Defy+ 手机和各种模拟器配置上。它不会发生在我的三星 Galaxy Tab II 10.1 上,我猜测这是功能更强大的硬件的功能,或者可能是更高级的 Android 版本。

4

0 回答 0