Ich habe eine Anwendung, die MP3-Dateien, die an einer öffentlichen URL verfügbar sind. Leider unterstützt der Server kein Streaming, aber das Android macht die Benutzererfahrung durchaus akzeptabel.Android JellyBean Netzwerk Media-Problem
Es funktioniert alles für alle Plattformen außer JellyBean. Beim Anfordern der MP3 fordert JB 10 Mal einen Range-Header an. Erst nach dem 10. Versuch scheint es zu dem alten Verhalten zurückzukehren. Looks like this already reported issue.
fand ich eine andere SO thread wo eine empfohlene Lösung Tranfer-Encoding zu verwenden ist: chunked-Header. Aber gerade unten gibt es einen Kommentar, dass dies nicht funktioniert.
Im Moment habe ich keinerlei Kontrolle über die obigen Antwortheader, aber bis ich dazu in der Lage bin, habe ich gedacht, auf der Clientseite nach einer Alternative zu suchen. (Trotzdem kann ich nur einen Inhaltsbereich zurückgeben, der Indizes von 0 bis Content-Length enthält - 1. Ex. Content-Range: Bytes 0-3123456/3123457).
Was ich zu tun versucht, ist ein Pseudo-Streaming auf Client-Seite zu implementieren durch:
- Öffnen Sie eine Eingabestrom auf den MP3.
- Decodieren Sie die eingehenden Bytes mit JLayer. Ich fand die Decodierung bei this link.
- Senden Sie die decodierten Array-Bytes an einen bereits abspielbaren Stream-Modus AudioTrack.
Das Stück Code, der die Dekodierung tut sind dort zu finden, habe ich geändert es nur so ist es ein Input erhalten:
public byte[] decode(InputStream inputStream, int startMs, int maxMs) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
float totalMs = 0;
boolean seeking = true;
try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (!done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (!seeking) {
// logger.debug("Handling header: " + frameHeader.layer_string());
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
if (output.getSampleFrequency() != 44100 || output.getChannelCount() != 2) {
throw new IllegalArgumentException("mono or non-44100 MP3 not supported");
}
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
return outStream.toByteArray();
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
throw new IOException("Decoder error: " + e);
}
}
ich die decodierten Bytes in der Zeit chunks suche nach: beginnend mit (0, 5000), so dass ich zuerst ein größeres Array habe, dann suche ich nach den nächsten Byte - Arrays, die über eine Sekunde reichen: (5000, 1000), (6000, 1000), (7000, 1000) usw .
Die Decodierung ist schnell genug und wird in einem anderen Thread durchgeführt und sobald ein decodiertes Byte-Array verfügbar ist, verwende ich eine blockierende Warteschlange zu schreibe es in den AudioTrack, der in einem anderen Thread abgespielt wird.
Das Problem ist, dass die Wiedergabe nicht reibungslos ist, da die Chunks in einer Spur nicht kontinuierlich sind (jeder Chunk ist kontinuierlich, aber in den AudioTrack hinzugefügt führt zu einer schlampigen Wiedergabe).
Zum Abschluss:
- Wenn Sie in diese JellyBean Problem gestoßen haben, wie haben Sie es lösen?
- Wenn einer von euch meinen Ansatz versucht hat, was mache ich dann oben falsch? Wenn dies die von Ihnen verwendete Lösung ist, kann ich den Rest des Codes veröffentlichen.
Vielen Dank!
Danke für die Antwort ... Ich möchte diesen Ansatz nicht für das Projekt, das ich brauchte, befolgen, aber wenn ich eines Tages Zeit haben werde, werde ich das vielleicht aus pädagogischen Gründen versuchen. Die offenen Fragen stehen also immer noch (Für JellyBean funktioniert das alles gut. Bei der Anforderung der MP3 bittet JB 10 Mal um einen Range-Header. Erst nach dem 10. Versuch scheint es wieder zu dem alten Verhalten zu kommen.) Wenn du darauf gestoßen bist, wie hast du das behoben? War es etwas von der Server-Seite oder war es Client-Seite? – gunar
Können Sie Ihren Code für diese Zeile einfügen: "Wenn JB die MP3 anfordert, bittet JB 10 Mal um einen Range-Header. Erst nach dem 10. Versuch scheint es wieder das alte Verhalten zu geben." – Matt
Ich habe keinen Code für JB hinzugefügt, um Range-Header anzufordern. Bitte werfen Sie einen Blick auf die [angehängte Android-Ausgabe] (https://code.google.com/p/android/issues/detail?id=35790). Alles bezieht sich darauf. – gunar