为了账号安全,请及时绑定邮箱和手机立即绑定

访问媒体播放器缓存

/ 猿问

访问媒体播放器缓存

DIEA 2019-12-27 15:44:31

完全加载后,我想将逐渐流式传输的mp3文件移动到sd卡。有什么方法可以实现这一目标。

我已经看到,MediaPlayer在逐步流式传输的同时完全下载了整个文件,然后我们可以搜索文件的任何部分。我想将完全流式传输的文件移至外部存储,以便将来的播放不会浪费数据和电池。



查看完整描述

3 回答

?
慕容708150

对原始帖子的评论将您指向正确的方向,但我认为对此加以说明可能会有所帮助...


我要做的是使用Apache HTTP库构建轻量级代理服务器。那里应该有很多例子,以了解这部分的基础知识。为MediaPlayer提供适当的本地主机URL,以便它打开代理的套接字。当MediaPlayer发出请求时,请使用代理将等效请求发送到实际的媒体主机。您将在代理的packetReceived方法中接收byte []数据,该数据用于构建HttpGet并通过AndroidHttpClient进行发送。


您将返回一个HttpResponse,并且可以使用内部的HttpEntity访问流字节数据。我正在使用ReadableByteChannel,如下所示:


HttpEntityWrapper entity = (HttpEntityWrapper)response.getEntity();

ReadableByteChannel src = Channels.newChannel(entity.getContent());

读回数据时,您可以对其进行任何处理(例如将其缓存在SD卡上的文件中)。要将正确的内容传递给MediaPlayer,请从客户端Socket获取SocketChannel,首先将响应标头直接写入该通道,然后继续写入实体的字节数据。我在while循环中使用NIO ByteBuffer(客户端是Socket,缓冲区是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

    }

}

您可能需要先更改响应中的主机头,然后再将其传递给播放器,以使您的代理看起来像是发送方,但是我正在处理MediaPlayer的专有实现,因此行为可能有所不同。希望能有所帮助。


查看完整回答
反对 回复 2019-12-27
?
慕侠2389804

这个想法是创建一个媒体播放器可以读取的代理,而不是直接从Web读取数据。


我使用了很简单的danikula / AndroidVideoCache来构建/使用。我将其用于音频而不是视频,但完全相同。


查看完整回答
反对 回复 2019-12-27
?
慕勒3428872

太晚了,但我发现大多数人仍然需要解决方案。我的解决方案基于JakeWharton的DiskLruCache。我们需要两件事


AsyncTask读取文件或从网络下载并缓存它


回调以从缓存中获取InputStram / FileDescriptor


步骤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();

    }

}

第2步:


public interface OnCacheCallback {


    void onSuccess(FileInputStream stream);


    void onError();

}


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);

注意:


这是经过测试的,但用于音频文件缓存的粗略示例,如果发现任何问题,可能会出现一些问题,请通知我:)


查看完整回答
反对 回复 2019-12-27

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信