NotificationPlayer.java
定義一個播放Notification聲音的player,本質上仍然是一個MediaPlayer,這個是多線程編程的很好的例子
public?class?NotificationPlayer?implements?OnCompletionListener?{
//發送播放和停止的cmd
private?static?final?int?PLAY?=?1;
private?static?final?int?STOP?=?2;
//對于多線程處理來說,這個class用來線程之間傳遞數據
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?+?"?}";
}
}
//播放類構造函數
public?NotificationPlayer(String?tag)?{
if?(tag?!=?null)?{
mTag?=?tag;
}?else?{
mTag?=?"NotificationPlayer";
}
}
public?void?play(Context?context,?Uri?uri,?boolean?looping,?int?stream)?{
//創建用于進程之間傳遞數據的類。前面說的那個中間class
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)?{
//開始另外一個線程,用來解析用戶設置cmd,然后才決定是play還是stop
enqueueLocked(cmd);
mState?=?PLAY;
}
}
//這表明CmdThread就是一個thread
private?final?class?CmdThread?extends?java.lang.Thread?{
CmdThread()?{
super("NotificationPlayer-"?+?mTag);
}
public?void?run()?{
while?(true)?{
Command?cmd?=?null;
synchronized?(mCmdQueue)?{
//這一步很巧妙,直接用隊列中刪除返回刪除數據的引用來獲取剛才在play中設置的信息
cmd?=?mCmdQueue.removeFirst();
}
switch?(cmd.code)?{
case?PLAY:
startSound(cmd);
break;
//主要是用戶發出停止的命令的操作--非正常播放結束stop
case?STOP:
……
//強制停止要釋放focus
mAudioManager.abandonAudioFocus(null);
break;
}
//處理之后要釋放wakelock
synchronized?(mCmdQueue)?{
if?(mCmdQueue.size()?==?0)?{
mThread?=?null;
releaseWakeLock();
return;
}
}
}
}
}//end?ofCmdThread
private?void?startSound(Command?cmd)?{
try?{
if((mLooper?!=?null)
&&?(mLooper.getThread().getState()?!=?Thread.State.TERMINATED))?{
mLooper.quit();
}
mCompletionThread?=?new?CreationAndCompletionThread(cmd);
//開啟播放線程
synchronized(mCompletionThread)?{
mCompletionThread.start();
mCompletionThread.wait();
}
}
}
private?final?class?CreationAndCompletionThread?extends?Thread?{
public?Command?mCmd;
public?CreationAndCompletionThread(Command?cmd)?{
super();
mCmd?=?cmd;
}
public?void?run()?{
try?{
//設置播放信息,并開始播放
MediaPlayer?player?=?new?MediaPlayer();
player.setAudioStreamType(mCmd.stream);
player.setDataSource(mCmd.context,?mCmd.uri);
player.setLooping(mCmd.looping);
player.prepare();
if?((mCmd.uri?!=?null)?&&?(mCmd.uri.getEncodedPath()?!=?null)
&&?(mCmd.uri.getEncodedPath().length()?>?0))?{
if?(mCmd.looping)?{
audioManager.requestAudioFocus(null,?mCmd.stream,
AudioManager.AUDIOFOCUS_GAIN);
}?else?{
audioManager.requestAudioFocus(null,?mCmd.stream,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
}
}
//這一步是必須的,要釋放focus
player.setOnCompletionListener(NotificationPlayer.this);
player.start();
}
}
}
public?void?onCompletion(MediaPlayer?mp)?{
if?(mAudioManager?!=?null)?{
mAudioManager.abandonAudioFocus(null);
}
}
}