Ho un'applicazione che sta riproducendo file MP3 che sono disponibili su un URL pubblico. Sfortunatamente il server non supporta lo streaming, ma l'Android rende l'esperienza dell'utente abbastanza accettabile.Problema di rete Android JellyBean
Funziona tutto bene per tutte le piattaforme tranne JellyBean. Quando si richiede l'MP3, JB richiede una Range-Header per 10 volte. Solo dopo il 10 ° tentativo sembra tornare al vecchio comportamento. Looks like this already reported issue.
Ho trovato un altro SO thread in cui una soluzione consigliata è utilizzare Tranfer-Encoding: intestazione chunked. Ma appena sotto c'è un commento che questo non funziona.
Per il momento non ho alcun controllo per fornire le intestazioni di risposta sopra, ma fino a quando non sarò in grado di farlo ho pensato di cercare un'alternativa sul lato client. (anche così, posso solo restituire un Content-Range che contiene indici da 0 a Content-Length - 1. Ex. Content-Range: byte 0-3123456/3123457).
Quello che ho cercato di fare è quello di implementare una pseudo-streaming sul lato client:
- Aprire un flusso di input per l'MP3.
- Decodifica i byte in entrata tramite JLayer. Ho trovato la decodifica a this link.
- Invia i byte dell'array decodificato a uno stream_mode AudioTrack già riproducibile.
Il pezzo di codice che effettua la decodifica può essere trovato lì, ho modificato solo così riceverà un InputStream:
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);
}
}
Sto richiedendo i byte decodificati in blocchi di tempo: iniziano (0, 5000) quindi avrò un array più grande da giocare in un primo momento, quindi richiedo gli array di byte successivi che si estendono su un secondo: (5000, 1000), (6000, 1000), (7000, 1000), ecc.
La decodifica è abbastanza veloce e viene eseguita in un altro thread e una volta decodificato un array di byte decodificato sto utilizzando una coda di blocco per scrivilo sull'AudioTrack che sta suonando in un'altra discussione.
Il problema è che la riproduzione non è fluida in quanto i pezzi non sono continui in una traccia (ogni blocco è continuo, ma aggiunto in AudioTrack risulta in una riproduzione sciatta).
Per concludere:
- Se avete urtato questo problema Jellybean, come hai fatto a risolverlo?
- Se qualcuno di voi ha provato il mio approccio, cosa sto facendo male nel codice sopra? Se questa è la soluzione che hai usato, posso pubblicare il resto del codice.
Grazie!
Grazie per aver risposto ... Non voglio seguire questo approccio per il progetto di cui avevo bisogno, ma se un giorno avrò un po 'di tempo libero, potrei provarlo per scopi educativi. Quindi le domande aperte rimangono valide (tutto funziona bene per tutte le piattaforme eccetto per JellyBean .Quando richiede l'MP3, JB richiede un Range-Header per 10 volte.) Solo dopo il 10 ° tentativo sembra tornare al vecchio comportamento.) Se ti sei imbattuto in questo, come hai risolto questo? Era qualcosa dal lato server o era lato client? – gunar
Potete includere il vostro codice per questa linea: "Quando si richiede l'MP3, JB richiede una Range-Header per 10 volte, solo dopo il 10 ° tentativo sembra tornare al vecchio comportamento." – Matt
Non ho aggiunto alcun codice per JB per richiedere l'intestazione di intervallo, per favore dare un'occhiata a [allegato problema Android] (https://code.google.com/p/android/issues/detail?id=35790). Tutto si riferisce ad esso. – gunar