我想在逐漸流式傳輸的mp3文件完全加載後移動到SD卡上。有什麼辦法可以實現這一點。訪問媒體播放器緩存
我見過的MediaPlayer
完全下載,而漸進式流整個文件,然後我們可以尋求文件的任何部分。我想將完整的流文件移動到外部存儲器,以便將來的播放不會浪費數據和電池。
我想在逐漸流式傳輸的mp3文件完全加載後移動到SD卡上。有什麼辦法可以實現這一點。訪問媒體播放器緩存
我見過的MediaPlayer
完全下載,而漸進式流整個文件,然後我們可以尋求文件的任何部分。我想將完整的流文件移動到外部存儲器,以便將來的播放不會浪費數據和電池。
在原來的崗位點你在正確的方向上的評論,但我認爲這可能有助於闡明有點...
我所做的是使用娜迦和建立一個輕量級的代理服務器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的如此行爲可能有點不同。希望有所幫助。
的想法是創建一個媒體播放器可以讀取的,而不是直接從網絡讀取數據,一個代理。
我用danikula/AndroidVideoCache這是非常簡單的建立/使用。 我用它作爲音頻而不是視頻,但它是一樣的。
這應該是正確的答案。直接和易於使用。我希望我能給10票。 – MetaSnarf
如何加密緩存文件? –
它的後期,但我發現大多數人仍然需要一個解決方案。我的解決方案基於JakeWharton's DiskLruCache。 我們需要兩樣東西
的AsyncTask讀取文件或從網絡上下載並緩存它
回調從緩存
第1步得到InputStram /的FileDescriptor:
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);
注:
這是測試,但對於音頻文件緩存粗糙的樣本,如果你發現有可能會出現一些問題什麼都請告知我:)
最佳答案她e,如果有人仍然在尋找解決方案: http://stackoverflow.com/a/12044709/1548464 – Taras