Acceso a la caché del reproductor multimedia

Quiero mover un archivo mp3 progresivamente transmitido a la tarjeta SD una vez que esté completamente cargado. ¿Hay alguna forma de lograrlo?

He visto que el MediaPlayer descarga completamente el archivo completo mientras que la transmisión progresiva y luego podemos buscar cualquier parte del archivo. Quiero mover un archivo completamente transmitido al almacenaje externo de modo que la reproducción futura no pierda datos y batería.

3 Solutions collect form web for “Acceso a la caché del reproductor multimedia”

El comentario sobre el post original te señala la dirección correcta, pero pensé que podría ser útil exponer un poco …

Lo que he hecho es construir un servidor proxy ligero usando Naga y las bibliotecas Apache HTTP. Debe haber un montón de ejemplos por ahí para obtener los fundamentos de esta parte. Proporcione al MediaPlayer una URL localhost apropiada para que abra un socket a su proxy. Cuando MediaPlayer realiza una solicitud, utilice el proxy para enviar una solicitud equivalente al host de medios actual. Recibirás datos byte [] en el método packetReceived del proxy, que utilizo para construir un HttpGet y enviarlo en su camino con AndroidHttpClient.

Usted recibirá una HttpResponse y puede utilizar la HttpEntity dentro para acceder a los datos de bytes de transmisión. Estoy usando un ReadableByteChannel, así:

 HttpEntityWrapper entity = (HttpEntityWrapper)response.getEntity(); ReadableByteChannel src = Channels.newChannel(entity.getContent()); 

Haga lo que quiera con los datos mientras lo lee de nuevo (como el caché en un archivo en la tarjeta SD). Para pasar el material correcto al MediaPlayer, obtenga el SocketChannel desde el cliente Socket, primero escriba los encabezados de respuesta directamente a ese canal y, a continuación, proceda a escribir los datos de bytes de la entidad. Estoy utilizando un NIO ByteBuffer en un bucle while (el cliente es un Socket y el búfer es un ByteBuffer).

 int read, written; SocketChannel dst = client.getChannel(); while (dst.isConnected() && dst.isOpen() && src.isOpen() && (read = src.read(buffer)) >= 0) { try { buffer.flip(); // This is one point where you can access the stream data. // Just remember to reset the buffer position before trying // to write to the destination. if (buffer.hasRemaining()) { written = dst.write(buffer); // If the player isn't reading, wait a bit. if (written == 0) Thread.sleep(15); buffer.compact(); } } catch (IOException ex) { // handle error } } 

Puede que tenga que alterar el encabezado de host en la respuesta antes de pasarlo junto al reproductor de modo que parece que su proxy es el remitente, pero estoy lidiando con una implementación propietaria de MediaPlayer para que el comportamiento podría ser un poco diferente. Espero que ayude.

La idea es crear un proxy que el reproductor multimedia pueda leer, en lugar de leer datos directamente desde la web.

He utilizado danikula / AndroidVideoCache que es muy simple de construir / usar. Lo usé para Audio no Video, pero es lo mismo.

Es tarde, pero me di cuenta de que la mayoría de la gente todavía necesita una solución. Mi solución basada en DiskLruCache de JakeWharton . Necesitamos dos cosas

  • AsyncTask para leer el archivo o descargarlo de la red y almacenarlo en caché

  • Devolución de llamada para obtener InputStram / FileDescriptor de caché

Paso 1:

 import android.content.Context; import android.os.AsyncTask; import org.apache.commons.io.IOUtils; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; // you can use FileDescriptor as // extends AsyncTask<String, Void, FileDescriptor> public class AudioStreamWorkerTask extends AsyncTask<String, Void, FileInputStream> { private OnCacheCallback callback = null; private Context context = null; public AudioStreamWorkerTask(Context context, OnCacheCallback callback) { this.context = context; this.callback = callback; } @Override protected FileInputStream doInBackground(String... params) { String data = params[0]; // Application class where i did open DiskLruCache DiskLruCache cache = MyApplication.getDiskCache(context); if (cache == null) return null; String key = hashKeyForDisk(data); final int DISK_CACHE_INDEX = 0; long currentMaxSize = cache.getMaxSize(); float percentageSize = Math.round((cache.size() * 100.0f) / currentMaxSize); if (percentageSize >= 90) // cache size reaches 90% cache.setMaxSize(currentMaxSize + (10 * 1024 * 1024)); // increase size to 10MB try { DiskLruCache.Snapshot snapshot = cache.get(key); if (snapshot == null) { Log.i(getTag(), "Snapshot is not available downloading..."); DiskLruCache.Editor editor = cache.edit(key); if (editor != null) { if (downloadUrlToStream(data, editor.newOutputStream(DISK_CACHE_INDEX))) editor.commit(); else editor.abort(); } snapshot = cache.get(key); } else Log.i(getTag(), "Snapshot found sending"); if (snapshot != null) return (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX); } catch (IOException e) { e.printStackTrace(); } Log.i(getTag(), "File stream is null"); return null; } @Override protected void onPostExecute(FileInputStream fileInputStream) { super.onPostExecute(fileInputStream); if (callback != null) { if (fileInputStream != null) callback.onSuccess(fileInputStream); else callback.onError(); } callback = null; context = null; } public boolean downloadUrlToStream(String urlString, OutputStream outputStream) { HttpURLConnection urlConnection = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); InputStream stream = urlConnection.getInputStream(); // you can use BufferedInputStream and BufferOuInputStream IOUtils.copy(stream, outputStream); IOUtils.closeQuietly(outputStream); IOUtils.closeQuietly(stream); Log.i(getTag(), "Stream closed all done"); return true; } catch (final IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) IOUtils.close(urlConnection); } return false; } private String getTag() { return getClass().getSimpleName(); } private String hashKeyForDisk(String key) { String cacheKey; try { final MessageDigest mDigest = MessageDigest.getInstance("MD5"); mDigest.update(key.getBytes()); cacheKey = bytesToHexString(mDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(key.hashCode()); } return cacheKey; } private String bytesToHexString(byte[] bytes) { // http://stackoverflow.com/questions/332079 StringBuilder sb = new StringBuilder(); for (byte aByte : bytes) { String hex = Integer.toHexString(0xFF & aByte); if (hex.length() == 1) sb.append('0'); sb.append(hex); } return sb.toString(); } } 

Paso 2:

 public interface OnCacheCallback { void onSuccess(FileInputStream stream); void onError(); } 

Ejemplo

 final String path = "http://www.example.com/test.mp3"; new AudioStreamWorkerTask (TestActivity.this, new OnCacheCallback() { @Override public void onSuccess(FileInputStream fileInputStream) { Log.i(getClass().getSimpleName() + ".MediaPlayer", "now playing..."); if (fileInputStream != null) { // reset media player here if necessary mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(fileInputStream.getFD()); mediaPlayer.prepare(); mediaPlayer.setVolume(1f, 1f); mediaPlayer.setLooping(false); mediaPlayer.start(); fileInputStream.close(); } catch (IOException | IllegalStateException e) { e.printStackTrace(); } } else { Log.e(getClass().getSimpleName() + ".MediaPlayer", "fileDescriptor is not valid"); } } @Override public void onError() { Log.e(getClass().getSimpleName() + ".MediaPlayer", "Can't play audio file"); } }).execute(path); 

Nota:

Esto se prueba pero la muestra ruda para la caché de archivos de audio, puede haber algunos problemas si encuentra algo por favor infórmenme 🙂

  • El streaming de MediaPlayer de Android para el cambio de red
  • Cómo silenciar MediaPlayer en android
  • Android - MediaController pierde la actividad
  • Cómo obtener la tasa de bits, tasa de muestreo y no. De canales de un archivo de audio en android
  • Cómo reproducir el archivo de sonido cuando se dispara GCMIntentService onMessage?
  • Error de MediaPlayer (-38, 0)
  • ¿Cómo puede reproducir medios de ftpserver sin descargarlo en android?
  • La reproducción de vídeo proporciona pantalla en negro pero con sonido
  • MediaPlayer / VideoView - Stream de una URL y luego guardar el video después de la caché?
  • El botón de reproducción de MediaController no se actualiza cuando se reproduce la canción
  • ¿Cómo reproducir varios vídeos en una vista de lista con MediaPlayer?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.