类概述
AsyncPlayer是android实现异步音乐播放的一个类,它将要播放的媒体文件封装成内部类Command。为了实现多个音乐播放,所有command都加在了 LinkedList中,当调用play或者stop方法的时候,会根据参数封装成一个command对象,启动一个thread,thread中会把LinkedList的第一个command弹出,根据command的code去判断是要播放还是停止,播放调用startSound()方法,停止则释放所有资源,当LinkedList中没有command,线程便停止。
播放一个连续(多个)的音频URLs,但那些任务较重的工作在另外的线程中完成,所以任何预处理或加载的延迟都不阻碍线程调用。
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log;
import java.io.IOException;
import java.lang.IllegalStateException;
import java.util.LinkedList;
public class AsyncPlayer {
private static final int PLAY = 1;
private static final int STOP = 2;
private static final boolean mDebug = false;
private static final class Command {
int code;
Context context;
Uri uri;
boolean looping;
int stream;
long requestTime;
public String toString() {
return "{ code=" + code + " looping=" + looping + " stream=" + stream + " uri=" + uri + " }";
}
}
private LinkedList mCmdQueue = new LinkedList();
private void startSound(Command cmd) {
try {
MediaPlayer player = new MediaPlayer();
player.setAudioStreamType(cmd.stream);
player.setDataSource(cmd.context, cmd.uri);
player.setLooping(cmd.looping);
player.prepare();
player.start();
if (mPlayer != null) {
mPlayer.release();
}
mPlayer = player;
} catch (IOException e) {
Log.w(mTag, "error loading sound for " + cmd.uri, e);
} catch (IllegalStateException e) {
Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
}
}
private final class Thread extends java.lang.Thread {
Thread() {
super("AsyncPlayer-" + mTag);
}
public void run() {
while (true) {
Command cmd = null;
synchronized (mCmdQueue) {
cmd = (Command) mCmdQueue.removeFirst();
}
switch (cmd.code) {
case PLAY:
startSound(cmd);
break;
case STOP:
if (mPlayer != null) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
} else {
Log.w(mTag, "STOP command without a player");
}
break;
}
synchronized (mCmdQueue) {
if (mCmdQueue.size() == 0) {
mThread = null;
releaseWakeLock();
return;
}
}
}
}
}
private String mTag;
private Thread mThread;
private MediaPlayer mPlayer;
private PowerManager.WakeLock mWakeLock;
private int mState = STOP;
public AsyncPlayer(String tag) {
if (tag != null) {
mTag = tag;
} else {
mTag = "AsyncPlayer";
}
}
public void play(Context context, Uri uri, boolean looping, int stream) {
Command cmd = new Command();
cmd.requestTime = SystemClock.uptimeMillis();
cmd.code = PLAY;
cmd.context = context;
cmd.uri = uri;
cmd.looping = looping;
cmd.stream = stream;
synchronized (mCmdQueue) {
enqueueLocked(cmd);
mState = PLAY;
}
}
public void stop() {
synchronized (mCmdQueue) {
if (mState != STOP) {
Command cmd = new Command();
cmd.requestTime = SystemClock.uptimeMillis();
cmd.code = STOP;
enqueueLocked(cmd);
mState = STOP;
}
}
}
private void enqueueLocked(Command cmd) {
mCmdQueue.add(cmd);
if (mThread == null) {
acquireWakeLock();
mThread = new Thread();
mThread.start();
}
}
public void setUsesWakeLock(Context context) {
if (mWakeLock != null || mThread != null) {
throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock + " mThread=" + mThread);
}
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
}
private void acquireWakeLock() {
if (mWakeLock != null) {
mWakeLock.acquire();
}
}
private void releaseWakeLock() {
if (mWakeLock != null) {
mWakeLock.release();
}
}
}