Chiunque abbia MediaPlayer Lavorare con ParcelFileDescriptor e createPipe ()?

Relativamente alla mia recente domanda su createPipe() e createPipe() e una discussione della tecnica createPipe() in questa altra domanda SO , sto cercando di get MediaPlayer a lavorare con i contenuti serviti da un ContentProvider tramite ParcelFileDescriptor e createPipe() .

Questo progetto di esempio ha il mio lavoro finora. È basato su un campione precedente che riproduce una clip OGG memorizzata come risorsa cruda . Quindi, so che la mia clip è buona.

  • MapFragment - NullPointerException - Google Maps V2 - Android
  • Android videoView mi dà l'allerta "Spiacente, questo video non può essere riprodotto"?
  • Tipo di risorsa XML mancante per PercentRelativeLayout Percentuale valore?
  • errore "imansible get BatchedBridge, assicurati che il tuo pacco sia confezionato correttamente" all'inizio dell'app
  • Fuori memory: android.support.v7.app.AppCompatActivity.onCreate
  • Imansible caricare librerie Opencv
  • Ho cambiato la mia impostazione di MediaPlayer su:

      private void loadClip() { try { mp=new MediaPlayer(); mp.setDataSource(this, PipeProvider.CONTENT_URI.buildUpon() .appendPath("clip.ogg") .build()); mp.setOnCompletionListener(this); mp.prepare(); } catch (Exception e) { goBlooey(e); } } 

    Attraverso l'accesso a PipeProvider , vedo che il mio Uri è stato costruito correttamente.

    PipeProvider è lo stesso di questo progetto di esempio , che funziona per la pubblicazione di PDF in Adobe Reader, che limita il modo in cui il mio codice può essere PipeProvider . 🙂

    In particolare, openFile() crea un pipe da ParcelFileDescriptor :

      @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { ParcelFileDescriptor[] pipe=null; try { pipe=ParcelFileDescriptor.createPipe(); AssetManager assets=getContext().getResources().getAssets(); new TransferTask(assets.open(uri.getLastPathSegment()), new AutoCloseOutputStream(pipe[1])).start(); } catch (IOException e) { Log.e(getClass().getSimpleName(), "Exception opening pipe", e); throw new FileNotFoundException("Could not open pipe for: " + uri.toString()); } return(pipe[0]); } 

    where il thread di background fa una copia stream-to-stream tipica:

      static class TransferTask extends Thread { InputStream in; OutputStream out; TransferTask(InputStream in, OutputStream out) { this.in=in; this.out=out; } @Override public void run() { byte[] buf=new byte[1024]; int len; try { while ((len=in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } catch (IOException e) { Log.e(getClass().getSimpleName(), "Exception transferring file", e); } } } 

    Tuttavia, soffocano MediaPlayer :

     10-16 13:33:13.203: E/MediaPlayer(3060): Unable to to create media player 10-16 13:33:13.203: D/MediaPlayer(3060): Couldn't open file on client side, trying server side 10-16 13:33:13.207: E/TransferTask(3060): Exception transferring file 10-16 13:33:13.207: E/TransferTask(3060): java.io.IOException: write failed: EPIPE (Broken pipe) 10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:462) 10-16 13:33:13.207: E/TransferTask(3060): at java.io.FileOutputStream.write(FileOutputStream.java:187) 10-16 13:33:13.207: E/TransferTask(3060): at com.commonsware.android.audiolstream.PipeProvider$TransferTask.run(PipeProvider.java:120) 10-16 13:33:13.207: E/TransferTask(3060): Caused by: libcore.io.ErrnoException: write failed: EPIPE (Broken pipe) 10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.Posix.writeBytes(Native Method) 10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.Posix.write(Posix.java:178) 10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191) 10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:457) 10-16 13:33:13.207: E/TransferTask(3060): ... 2 more 10-16 13:33:13.211: E/MediaPlayer(3060): Unable to to create media player 10-16 13:33:13.218: E/TransferTask(3060): Exception transferring file 10-16 13:33:13.218: E/TransferTask(3060): java.io.IOException: write failed: EPIPE (Broken pipe) 10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:462) 10-16 13:33:13.218: E/TransferTask(3060): at java.io.FileOutputStream.write(FileOutputStream.java:187) 10-16 13:33:13.218: E/TransferTask(3060): at com.commonsware.android.audiolstream.PipeProvider$TransferTask.run(PipeProvider.java:120) 10-16 13:33:13.218: E/TransferTask(3060): Caused by: libcore.io.ErrnoException: write failed: EPIPE (Broken pipe) 10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.Posix.writeBytes(Native Method) 10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.Posix.write(Posix.java:178) 10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191) 10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:457) 10-16 13:33:13.218: E/TransferTask(3060): ... 2 more 

    Qualcuno ha visto il codice di lavoro per l'utilizzo di createPipe() per servire i media a MediaPlayer ?

    Grazie in anticipo!

  • C'è un modo per utilizzare una dimensione delle banner pubblicitarie variables?
  • Come creare una schermata di scorrimento (come in Tweetdeck) in Android?
  • Come caricare il file di image in Retrofit 2
  • Come ottengo Android per rispondere alle tracce di touch?
  • ListView OnItemClickListener non ascolta
  • Best practice per mostrare i grandi dati di text in una vista android?
  • 3 Solutions collect form web for “Chiunque abbia MediaPlayer Lavorare con ParcelFileDescriptor e createPipe ()?”

    Non sono sicuro che questo possa funzionare. Quando eseguo questo codice vedo questa traccia:

     I/AudioSystem(30916): getting audio flinger I/AudioSystem(30916): returning new audio session id D/IAudioFlinger(30916): newAudioSessionId In D/AudioFlinger(28138): nextUniqueId, current 178 D/IAudioFlinger(30916): newAudioSessionId Out, id = 178 D/MediaPlayer(30916): setDataSource(Context context, content://com.commonsware.android.audiolstream/clip.ogg, Map<String, String> headers) in D/MediaPlayer(30916): setDataSource(FileDescriptor fd) in E/MediaPlayerService(28138): offset error 

    Quel "errore offset" deriva dalle seguenti righe in MediaPlayerService.cpp in AOSP, where fa un fstat () sul lato di lettura del pipe:

     status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length) { struct stat sb; int ret = fstat(fd, &sb); .... if (offset >= sb.st_size) { LOGE("offset error"); ::close(fd); return UNKNOWN_ERROR; } 

    E sb.st_size viene riportto come -1 (via getStatSize () sul ParcelFileDescriptor a livello Java). Il gestore di errori chiude il descrittore, quindi l'errore di pipe rotto poco dopo.

    Nella mia esperienza MediaPlayer ha molti bit spezzati come questo. Non ho mai visto che funzioni per qualsiasi cosa, ma direttamente nei file locali e (molto buggy) per lo streaming HTTP. Ho finito portndo FFmpeg a lavorare intorno ai suoi numerosi fallimenti.

    Ho cercato di utilizzare tubi con MediaPlayer tramite un ContentProvider usando PipeDataWriter (che usa sostanzialmente un pipe e un thread).

    Il problema è che il descrittore di file atteso dal MediaPlayer, alless per i contenuti video, deve essere richiesto e non puoi fare un fseek su un pipe.

    Nella tesi, openAssetFile() sul ContentProvider può essere ContentProvider . Un AssetFileDescriptor può essere restituito con dimensione dichiarata e offset.

     @Override public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { ParcelFileDescriptor fd = openFile(uri, mode); return fd != null ? new AssetFileDescriptor(fd, offset, size) : null; } 

    Questi valori vengono passati a setDataSource() nativo setDataSource() su MediaPlayer (controlla MediaPlayer.java per ulteriori informazioni).

    Se il controllo degli errori in MediaPlayerService.cpp è (offset> = sb.st_size), un errore offset inferiore a -1 (la dimensione presunta del contenuto) o una dimensione dichiarata positiva non innesca l'errore.

    Questo dovrebbe essere un buon punto di partenza per un hack pulito, ma ho una brutta fortuna nei miei test. Il duro MediaPlayer sembra leggere l'integer "file" prima di giocare, causando un pipe rotto in avanti.

    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.