Domanda

Vorrei utilizzare un InputStream arbitrario come origine dati per un oggetto MediaPlayer.

La ragione di questo è che l'InputStream sto utilizzando è in realtà un autorizzato connessione HTTPS a una risorsa multimediale su un server remoto. Passando l'URL in questo caso, ovviamente, non funzionerà come è necessaria un'autenticazione. Posso però fare l'autenticazione separatamente e ottenere un InputStream alla risorsa -? Problema è che cosa devo fare una volta l'ho

ho pensato alla possibilità di utilizzare un named pipe e passando la sua FileDescriptor al metodo setDataResource di MediaPlayer. C'è un modo per creare named pipe in Android (senza l'utilizzo di NDK)?

Ogni altro suggerimento è il benvenuto.

È stato utile?

Soluzione 2

Un'altra soluzione potrebbe essere quella di avviare un server proxy HTTP su localhost. Il lettore multimediale si connetterà a questo server con setDataSource (contesto Context, Uri uri). Questa soluzione funziona meglio rispetto al precedente e non causa la riproduzione per problema tecnico.

Altri suggerimenti

Credo di aver trovato una soluzione. Vi sarei grato se gli altri che sono interessati avrebbero cercato questo da soli e riferire i risultati con i loro modelli di dispositivi e la versione SDK.

ho visto i messaggi simili che direttamente a questo, ma ho pensato di postare comunque dal momento che è più recente e sembra funzionare su versioni più recenti del SDK - finora funziona sul mio Nexus One con sistema operativo Android 2.3.6 <. / p>

La soluzione si basa sulla bufferring flusso di input in un file locale (ho questo file sulla memoria esterna, ma probabilmente sarà possibile posizionarlo sul stoccaggio intenal pure) e fornendo descrittore di file per l'istanza MediaPlayer.

I seguenti viene eseguito in una modalità doInBackground di qualche AsyncTask che fa AudioPlayback:

@Override
protected
Void doInBackground(LibraryItem... params)
{
    ...

    MediaPlayer player = new MediaPlayer();
    setListeners(player);

    try {
        _remoteStream = getMyInputStreamSomehow();
        File tempFile = File.createTempFile(...);
        tempFile.deleteOnExit();
        _localInStream = new FileInputStream(tempFile);
        _localOutStream = new FileOutputStream(tempFile);
        int buffered = bufferMedia(
            _remoteStream, _localOutStream, BUFFER_TARGET_SIZE      // = 128KB for instance
        );

        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setDataSource(_localInStream.getFD());
        player.prepareAsync();

        int streamed = 0;
        while (buffered >= 0) {
            buffered = bufferMedia(
                _remoteStream, _localOutStream, BUFFER_TARGET_SIZE
            );
        }
    } 
    catch (Exception exception) {
        // Handle errors as you see fit
    }

    return null;
}

I bufferMedia metodo buffer nBytes byte o fino al raggiungimento della fine dell'input:

private
int bufferMedia(InputStream inStream, OutputStream outStream, int nBytes)
throws IOException
{
    final int BUFFER_SIZE = 8 * (1 << 10);
    byte[] buffer = new byte[BUFFER_SIZE];          // TODO: Do static allocation instead

    int buffered = 0, read = -1;
    while (buffered < nBytes) {
        read = inStream.read(buffer);
        if (read == -1) {
            break;
        }           
        outStream.write(buffer, 0, read);
        outStream.flush();
        buffered += read;
    }

    if (read == -1 && buffered == 0) {
        return -1;
    }

    return buffered;
}

Il metodo setListeners imposta gestori per vari eventi MediaPlayer. La più importante è quella del OnCompletionListener che viene richiamato quando la riproduzione è stata completata. In caso di svuotamento del buffer (a causa, per esempio, connessione temporanea di rete lenta) il giocatore raggiungerà la fine del file locale e di transito per lo Stato PlaybackCompleted. Mi identifico quelle situazioni confrontando il posizione _localInStream contro la dimensione del flusso di ingresso. Se la posizione è più piccolo, quindi la riproduzione è ora davvero completata e I ha ripristinato il MediaPlayer:

private
void setListeners(MediaPlayer player)
{
    // Set some other listeners as well

    player.setOnSeekCompleteListener(
        new MediaPlayer.OnSeekCompleteListener()
        {
            @Override
            public
            void onSeekComplete(MediaPlayer mp)
            {
                mp.start();
            }
        }
    );

    player.setOnCompletionListener(
        new MediaPlayer.OnCompletionListener() 
        {
            @Override
            public 
            void onCompletion(MediaPlayer mp) 
            {
                try {
                    long bytePosition = _localInStream.getChannel().position();
                    int timePosition = mp.getCurrentPosition();
                    int duration = mp.getDuration();

                    if (bytePosition < _track.size) {                           
                        mp.reset();
                        mp.setDataSource(_localInStream.getFD());
                        mp.prepare();
                        mp.seekTo(timePosition);
                    } else {                            
                        mp.release();
                    }
                } catch (IOException exception) {
                    // Handle errors as you see fit
                }
            }
        }
    );
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top