1) MediaPlayer
ist nicht das richtige Werkzeug für diesen Job. Schauen Sie sich SoundPool
an. Es ist für kurze Sounds vorgesehen, die wiederholt abgespielt werden.
2) Für Ihren Fall, was Sie wollen, ist nicht wirklich eine Schleife. Die Sounds werden asynchron gespielt, so dass Sie in die Situation geraten, in der sich die Calls aufeinander stapeln. Das führt dazu, dass der native Code von MediaPlayer
die verfügbaren Ressourcen erschöpft.
Was Sie wollen, ist eine Reihe von Rückrufen. Die MediaPlayer
hat den Completion Callback, den Sie bereits verwenden, aber das scheint genau das zu sein, was benötigt wird, aber für Ihren Anwendungsfall reicht es nicht aus. Der systemeigene Code für MediaPlayer
wird nicht in der Lage sein, seine Ressourcen schnell genug für jeden nachfolgenden Aufruf freizugeben, und die gleiche Erschöpfung der Ressourcen wird auftreten. Das ist nur eine unglückliche Realität für die Funktionsweise der MediaPlayer
.
SoundPool
hat nicht diesen bequemen Abschluss Callback, aber in diesem Fall haben Sie wahrscheinlich nur zwei Klangbeispiele und Sie wissen, wie lange sie sind. Eine einfache Timer-Verzögerung wird wahrscheinlich ausreichen. Sie können Handler.postDelayed
verwenden, um diesen Effekt zu erzielen. In jedem Callback-Event spielen Sie einfach den nächsten Sound, fahren Sie mit der von Ihnen verwendeten Variable fort, um den aktuellen Sound zu verfolgen, und posten Sie denselben Callback erneut, um alle verbleibenden Sounds abzuspielen. Es ist eine Art asynchrone Schleife.
UPDATE
um zu verstehen, was los ist, hier ist ein wenig aus der Dokumentation des Android auf Handler
:
Ein Handler ermöglicht es Ihnen, Nachrichten- und Runnable Objekte zu senden und Verfahren mit einem Message Thread zugeordnet ist. Jede Handler-Instanz ist einem einzelnen Thread und der Nachrichtenwarteschlange dieses Threads zugeordnet. Wenn Sie einen neuen Handler erstellen, wird er an die Thread-/Nachrichtenwarteschlange des Threads gebunden, der ihn erstellt. Ab diesem Zeitpunkt werden Nachrichten und Runnables an diese Nachrichtenwarteschlange übergeben und ausgeführt, sobald sie aus der Nachricht kommen Warteschlange.
Also, wenn meine Vermutung über Ihre Code-Struktur nahe zu korrigieren, würden Sie ein Handler
Objekt als Mitglied Ihrer Activity
Klasse erstellen. Dadurch wird es an den GUI-Thread gebunden, was in Ordnung sein sollte, da Sie dort nicht viel arbeiten werden. Sie benötigen auch eine Runnable
, um als die Aufgabe zu fungieren, die gepostet wird. Machen Sie es auch zu einem Mitglied Ihrer Klasse. Und Sie werden Ihre String
brauchen, die die Charaktere enthält, um ein Mitglied zu sein. Und Sie benötigen eine int
, um zu verfolgen, welcher Charakter Sie gerade sind.
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);
}
};
Überall dort, wo Sie die Klänge zu spielen beginnen möchten, rufen Sie einfach:
charIndex = 0;
playMorseHandler.post(playMorseTask);
Das einzige, was wäre bei Ihrer startPlayback()
Methode das Richtige zu tun, machen, die SoundPool
zu verwenden anstelle von MediaPlayer
. Das liegt daran, dass, wie ich bereits erwähnt habe, MediaPlayer
unweigerlich dazu führen wird, dass dem System Ressourcen ausgehen, die diese kurzen Töne so schnell zusammen spielen.
Ive sah sich um, aber kann nicht herausfinden, wie man den einfachen Handler.postDelayed implementiert, können Sie ein Codebeispiel bereitstellen? –
Der Code ive versucht scheint zu arbeiten und Verzögerungen vor dem Ausführen des Codes, aber die Schleife wartet nicht. Ich bin mir nicht sicher, wie ich es wiederholen soll, so dass ich eine Menge Zeit warten kann, bevor ich fortfahre. @Dave –
Ich wollte, dass Sie überhaupt keine for-Schleife verwenden. Es ist nicht das richtige Konstrukt zu verwenden. Stattdessen müssen Sie einen Callback verwenden, der sich selbst als Looping-Mechanismus bezeichnet. Ich werde meine Antwort in Kürze aktualisieren, um zu zeigen, was ich meine, aber ich weiß nicht annähernd genug über Ihr Projekt, um etwas zu liefern, das einfach funktionieren wird. Sie müssen es testen und versuchen, einige Dinge selbst zu erledigen. – Dave