[英]Wait for sound to finish before continuing
我正在創建一個循環遍歷字符串的循環,並根據顯示的字符播放不同的聲音。 不幸的是,它不會等待聲音結束才繼續播放,這會導致媒體播放器出錯。 我的循環看起來像這樣:
for (char ch : morsechars) {
if (Character.toString(ch).equals(".") ) {
Log.d("play: ", "dot");
try {
startPlayback();
} catch (Exception e){
e.printStackTrace();
}
} else if (Character.toString(ch).equals("-")){
Log.d("play: ", "dash");
try {
startPlayback();
} catch (Exception e){
e.printStackTrace();
}
}
}
而我的播放器如下所示:
public void startPlayback() throws Exception{
play = MediaPlayer.create(this, dotFILE);
play.start();
isplaying = true;
while (isplaying == true){
}
play.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer play) {
isplaying = false;
play.stop();
play.reset();
play.release();
}
});
}
我不確定如何在繼續到循環中的下一個字符之前等待完成偵聽器。
1) MediaPlayer
不是適合此工作的工具。 看一下SoundPool
。 它適用於反復播放的短聲音。
2)對於您的情況,您想要的並不是真正的循環。 聲音將異步播放,因此您遇到了這樣的情況:要播放的呼叫相互疊加。 這將導致MediaPlayer
的本機代碼耗盡可用資源。
您想要的是一系列回調。 MediaPlayer
具有您已經在使用的完成回調,但是,盡管這看起來確實是需要的,但它不足以滿足您的用例。 MediaPlayer
本機代碼將無法足夠快地釋放其資源以供隨后的每個播放調用使用,並且將發生相同的資源耗盡。 對於MediaPlayer
工作方式,這只是一個不幸的現實。
SoundPool
沒有方便的完成回調,但是在這種情況下,您可能只有兩個聲音樣本,並且知道它們有多長時間。 一個簡單的計時器延遲可能就足夠了。 您可以使用Handler.postDelayed
實現此效果。 在每個回調事件中,只需播放下一個聲音,前進用於跟蹤當前聲音的任何變量,然后再次發布相同的回調以播放所有剩余聲音。 這是一種異步循環。
UPDATE
為了幫助您了解發生了什么,這里有一些關於Handler
Android文檔:
處理程序使您可以發送和處理與線程的MessageQueue關聯的Message和Runnable對象。 每個Handler實例都與一個線程和該線程的消息隊列關聯。 創建新的Handler時,它將綁定到正在創建它的線程的線程/消息隊列中-從那時起,它將把消息和可運行對象傳遞到該消息隊列,並在它們從消息中出來時執行它們隊列。
因此,如果我對您的代碼結構的猜測接近正確,則可以創建一個Handler
對象作為Activity
類的成員。 這會將其綁定到GUI線程,這應該沒問題,因為在那里您不會做很多工作。 您還需要一個Runnable
來充當要發布的任務。 也使其成為班上的一員。 並且您將需要包含字符的String
成為成員。 並且您將需要一個int
來跟蹤當前使用的字符。
private Handler playMorseHandler = new Handler();
private String morseChars = ".--...---"; // I don't know where you set this
private int charIndex = 0;
private Runnable playMorseTask = new Runnable() {
if (morseChars == null ||
charIndex < 0 ||
charIndex >= morseChars.length()) {
Log.w("whateverTag", "Basic assumptions failed");
return;
}
char ch = morseChars.charAt(charIndex);
long lengthOfClip = 0L;
boolean postAgain = true;
if (ch == '.') {
Log.d("play: ", "dot");
lengthOfClip = 300L; // I don't know how long your clips are
try {
startPlayback();
} catch (Exception e){
e.printStackTrace();
}
} else if (ch == '-') {
Log.d("play: ", "dash");
lengthOfClip = 500L; // I don't know how long your clips are
try {
startPlayback();
} catch (Exception e){
e.printStackTrace();
}
} else {
Log.d("whateverTag", "unexpected input");
postAgain = false;
}
++charIndex;
if (postAgain && charIndex < morseChars.length()) {
playMorseHandler.postDelayed(this, lengthOfClip);
}
};
無論您想在哪里開始播放聲音,只需調用:
charIndex = 0;
playMorseHandler.post(playMorseTask);
剩下的唯一事情就是讓您的startPlayback()
方法做正確的事情,那就是使用SoundPool
而不是MediaPlayer
。 這是因為,正如我前面提到的那樣, MediaPlayer
不可避免地會導致系統耗盡所有資源,因此很快地播放這些短聲音。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.