1)MediaPlayer
はこの仕事には適していません。 SoundPool
を見てください。繰り返し再生される短い音を対象としています。
2)あなたの場合は、実際にはループではありません。サウンドは非同期で再生されるため、再生するコールが互いに重ね合わされた状態になります。これにより、MediaPlayer
のネイティブコードが利用可能なリソースを使い果たすことになります。
あなたが望むのは、一連のコールバックです。 MediaPlayer
にはすでに使用している完了コールバックがありますが、必要なものと正確には見えますが、ユースケースでは十分ではありません。 MediaPlayer
のネイティブコードは、後続の呼び出しが再生されるのに十分速くリソースを解放することができず、同じリソースが使い果たされます。それはMediaPlayer
がどのように機能するかについての不幸な現実です。
SoundPool
には便利な補完コールバックがありませんが、この場合はおそらく2つのサウンドサンプルしかなく、どれくらいの長さであるかがわかります。おそらく、単純なタイマーの遅延で十分です。この効果を得るにはHandler.postDelayed
を使用できます。各コールバックイベントでは、次のサウンドを再生し、現在のサウンドを追跡するために使用している変数を前に進め、同じコールバックを再度ポストして残りのサウンドを再生します。それは非同期ループの一種です。ここでは、何が起こっているか理解するために
UPDATE
がHandler
にAndroidのドキュメントからのビットは次のとおりです。
Aハンドラを使用すると、スレッドのメッセージキューに関連付けられたメッセージとのRunnableオブジェクトを送信して処理することができます。各Handlerインスタンスは、単一のスレッドとそのスレッドのメッセージキューに関連付けられています。新しいHandlerを作成すると、それを作成しているスレッドのスレッド/メッセージキューにバインドされます。その時点から、そのメッセージキューにメッセージと実行可能ファイルを配信し、メッセージから出てくるように実行しますキュー。あなたのコードの構造についての私の推測では、修正するために近ければ
だから、あなたはあなたのActivity
クラスのメンバとしてHandler
オブジェクトを作成します。これはそれをGUIスレッドにバインドします。あなたはそこで多くの作業をしないのでOKです。投稿されるタスクとして機能するには、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
は必然的にシステムがこれらの短い音をすばやく再生するリソースを使い果たしてしまうからです。
Iveは見て回りましたが、単純なHandler.postDelayedを実装する方法を見つけることができないようですが、コードサンプルを提供できますか? –
コードを実行しようとする前に動作し遅延しているようですが、ループは待機しません。それをやり直す方法がわからないので、私は継続する前にある程度の時間を待つことができます。 @Dave –
あなたはforループをまったく使用しないことを意図していました。それは使用する正しい構成体ではありません。代わりに、自分自身をループ機構として呼び出すコールバックを使用する必要があります。私はちょっと私の答えを更新して、私が何を意味するのかを示しますが、ちょうどうまくいくものを提供するあなたのプロジェクトについては十分に分かりません。あなたはそれをテストし、あなた自身でいくつかのことを試してみる必要があります。 – Dave