Android Media Player – Wie deaktiviere ich Reichweite? (Defektes Audio-Streaming auf Nexus 7)

Ich habe eine Audio-Streaming-App, die einen lokalen Proxy-Server ausführt. Der lokale Proxy-Server macht eine http-Verbindung zu einer Internet-Streaming-Quelle, bekommt und puffert lokal die Streaming-Daten. Dann, innen in der app, benutze ich MediaPlayer, um mit dem lokalen Proxy-Server zu verbinden, mit der Methode

mediaPlayer.setDataSource(...); // the url of the local proxy server 

Alles war in Ordnung (mit vielen Android-Geräten und verschiedenen OS-Versionen – 1.5 … 4.0), bis Nexus 7 Release.

  • FLAG_ACTIVITY_CLEAR_TOP in Android
  • Portierung eines SDL 2.0 Spiels auf Android
  • Verwenden Sie RxAndroid oder RxKotlin bei der Programmierung in Kotlin für Android?
  • Android besten und sicheren Weg, um Thread zu stoppen
  • Wie kann man auf Berührungsereignis respektieren
  • Wie man eine Referer-Anfrage in einer URL für ein WebView sendet
  • In Nexus 7 weigert sich der Mediaplayer, die Quelle vom lokalen Proxy-Server zu spielen.

    Als ich einen Blick auf die Protokolle werfe, scheint der MediaPlayer Bereichsanforderungen intern zu verwenden. Mein lokaler Proxy-Server behandelt das nicht. Es gibt HTTP / 1.0 200 OK und die Daten zurück. Der Media Player mag das aber nicht und wirft eine Ausnahme aus:

     Caused by: libcore.io.ErrnoException ?:??: W/?(?): [ 07-18 00:08:35.333 4962: 5149 E/radiobee ] ?:??: W/?(?): : sendto failed: ECONNRESET (Connection reset by peer) ?:??: W/?(?): at libcore.io.Posix.sendtoBytes(Native Method) ?:??: W/?(?): at libcore.io.Posix.sendto(Posix.java:146) ?:??: W/?(?): at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java: ?:??: W/?(?): at libcore.io.IoBridge.sendto(IoBridge.java:473) We requested a content range, but server didn't support that. (responded with 200) 

    Nach den http-Spezifikationen, wenn der Server mit HTTP / 1.0 statt 1.1 antwortet, darf der Client keine Reichweitenanforderung auslösen (1.0 unterstützt das sowieso nicht)

    Auch wenn der Server die Reichweitenanforderung nicht unterstützt, sollte es gut sein, wenn es mit 200 OK antwortet (und das ist was ich tue), aber die MediaPlayer-Implementierung auf Nexus 7 mag das nicht.

    Ich habe einen Blick auf diesen Thread geworfen: HTTP: Wie soll ich auf "Range: bytes =" antworten, wenn Range nicht unterstützt wird?

    , Wo sie behaupten, dass die Antwort mit 200 OK muss gut genug sein, aber leider hilft es nicht.

    Ich bin mir nicht sicher, ob dies ein Problem mit Jelly Bean ist, oder ein Problem mit Nexus 7 Implementierung speziell, aber es ist immer noch ein Problem für mich, die ich zu lösen habe.

    Wieder gibt es keine Bereichsanforderungen auf viele andere Android-Geräte, mit der gleichen App. Aus irgendeinem Grund passieren diese Streckenanforderungen jetzt auf Nexus 7. (Es kann auch auf anderen Android-Geräten passieren, aber wieder ist mir noch nie passiert).

    Mögliche Möglichkeit, die Bereichsanforderungen für MediaPlayer zu deaktivieren?

    Wenn es keine gibt, kann jemand vorschlagen, eine schnelle Lösung für meine Proxy-Server-Logik (was genau muss es zurückkehren, wenn es diese Reichweite anfordern?), Ohne meine andere Logik, wenn möglich zu ändern?

    Scheint wie vielleicht muss ich so etwas zurückgeben wie "HTTP / 1.0 206 OK \ r \ nPartial Content \ r \ n \ r \ n", aber wahrscheinlich sollte es einen Wert am Ende des Teilinhalts geben – nicht sicher, was ist Sei dieses

    Ihre Hilfe wäre willkommen.

    Vielen Dank..

  • Ist jemand da draußen mit Robolectric ohne Maven auf IntelliJ?
  • Testen Sie, dass Admob vor dem Veröffentlichen arbeitet
  • Ist dieser benutzerdefinierte CursorAdapter für eine ListView richtig für Android codiert?
  • Wie bekomme ich die Android ID für einen Menüpunkt in Android?
  • Erstellen Sie JSON String mit GSON
  • Wie bekomme ich Android App mit externem MySQL db
  • 3 Solutions collect form web for “Android Media Player – Wie deaktiviere ich Reichweite? (Defektes Audio-Streaming auf Nexus 7)”

    Wir haben das endlich sauber gelöst. In unserem Fall haben wir die volle Kontrolle über den Streaming-Server, aber ich denke, du könntest dies auch mit einem lokalen Proxy machen. Da Build.VERSION_CODES.ICE_CREAM_SANDWICH es möglich, Header für das MediaPlayer Objekt zu setzen. Da unsere App es dem Benutzer ermöglicht, innerhalb des Audio-Streams zu suchen, haben wir diesen Range Header auf dem Client implementiert. Wenn der Server mit den richtigen Headern antwortet, versucht der MediaPlayer nicht mehrmalig, den Stream anzufordern.

    Das ist, was unsere Server-Header jetzt für den Android-Client aussehen:

     Content-Type: audio/mpeg Accept-Ranges: bytes Content-Length: XXXX Content-Range: bytes XXX-XXX/XXX Status: 206 

    Der wichtige Teil ist der 206 Statuscode (Teilinhalt). Wenn Sie diesen Header nicht senden, wird der Android-Client versuchen, die Quelle erneut anzufordern, egal was.

    Wenn dein Spieler es nicht zulässt, im Stream zu suchen, kannst du einfach den Range Header auf 0-some arbitrary large number einstellen 0-some arbitrary large number .

    Ich arbeite an einer groß angelegten Audio-Streaming-App (die einen lokalen Host-HTTP-Proxy verwendet, um Audio auf MediaPlayer zu streamen) und ich lief in dieses Problem, sobald ich ein JellyBean-Gerät in meinen Händen bei Google I / O 2012 bekam.

    Bei der Qualitätsprüfung unserer Anwendung auf verschiedenen Geräten (und mit Informationen, die von unseren automatisierten Crash-Logs und vom Benutzer eingereichten Protokollen erhalten wurden), haben wir festgestellt, dass sich bestimmte MediaPlayer-Implementierungen verhalten haben, was ich eine unberechenbare (und manchmal geradezu psychotische) Weise nennen würde.

    Ohne zu viel Detail zu gehen, das ist, was ich sah: einige Implementierungen würden mehrere Anfragen (manchmal 5+) für die gleiche URL machen. Diese Anfragen waren alle leicht voneinander verschieden, da jeder für einen anderen Bytebereich war (normalerweise für die ersten oder letzten 128 Bytes). Die Schlussfolgerung war, dass der MediaPlayer versucht, eingebettete Metadaten zu finden, dann würde es nach einiger Zeit aufgeben und nur eine regelmäßige Non-Range-Anfrage machen.

    Das ist nicht das, was die Aktie JellyBean MediaPlayer-Implementierung macht, sondern nur ein Beispiel für die Whacky-Ness und die allgemeine Fragmentierung des Media Frameworks auf Android. Allerdings war die Lösung für die oben genannte Situation auch die Lösung für das JellyBean Problem, und das ist:

    Haben Sie Ihren lokalen Proxy mit Chunked-Codierung antworten

    Dies ersetzt den Content-Length-Header mit einem Tranfer-Encoding: Chunked Header. Dies bedeutet, dass der anfordernde Client die Gesamtlänge der Ressource nicht kennt und somit keine Reichweitenanforderung machen kann, sondern nur die Chunks, wie sie empfangen werden.

    Wie ich schon sagte, das ist ein Hack, aber es funktioniert. Es ist nicht ohne seine Nebenwirkungen: Media Player Puffer Fortschritt wird falsch sein, da es nicht wissen, die Länge der Audio (ist einer von ihnen), um zu bekommen, dass Sie Ihre eigene Pufferung Berechnung verwenden müssen (Sie sind Streaming Von irgendwo durch deinen Proxy zum MediaPlayer, richtig, also wirst du die Gesamtlänge kennen).

    Wenn Sie suchen oder überspringen oder die Verbindung verloren geht und MediaPlayer die Verbindung zum Proxy-Server wieder herstellt, müssen Sie diese Antwort mit Status 206 senden, nachdem Sie die Anforderung und den Bereich (int) vom Client erhalten haben.

     String headers += "HTTP/1.0 206 OK\r\n"; headers += "Content-Type: audio/mpeg\r\n"; headers += "Accept-Ranges: bytes\r\n"; headers += "Content-Length: " + (fileSize-range) + "\r\n"; headers += "Content-Range: bytes "+range + "-" + fileSize + "/*\r\n"; headers += "\r\n"; 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.