符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
这篇文章主要为大家展示了“Android视频/音频缓存框架AndroidVideoCache怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Android视频/音频缓存框架AndroidVideoCache怎么用”这篇文章吧。
创新互联是一家专注于网站设计、成都网站设计与策划设计,范县网站建设哪家好?创新互联做网站,专注于网站建设十多年,网设计领域的专业建站公司;建站业务涵盖:范县等地区。范县做网站价格咨询:13518219792
具体内容如下
对于视频/音频软件,音乐软件,视频软件,都有缓存这个功能,那如何实现边下边播功能:
如何实现这个边下边播功能?
文件是否支持同时读写?(Mediaplayer 播放文件,从网络上下载文件)
播放与下载进度如何协调?
已缓存的文件需及时清理
经过一番折腾,我 find 了 : [ AndroidVideoCache ],这个库是 danikula 大神写,看完源码后收益匪浅。实现流媒体边下边播原理利用socket 开启一个本机的代理服务器
结合自身需求,修改了该库,使用okhttp进行网络请求:
AndroidVideoCache (改成 okhttp 缓存)
package com.danikula.videocache; import android.text.TextUtils; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.util.Map; import java.util.concurrent.TimeUnit; import com.danikula.videocache.file.MyLog; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import static com.danikula.videocache.ProxyCacheUtils.DEFAULT_BUFFER_SIZE; import static com.danikula.videocache.ProxyCacheUtils.LOG_TAG; import static java.net.HttpURLConnection.HTTP_OK; import static java.net.HttpURLConnection.HTTP_PARTIAL; /** * {@link Source} that uses http resource as source for {@link ProxyCache}. * * @author Alexey Danilov (danikula@gmail.com). * * 从URL 获取数据 */ public class HttpUrlSource implements Source { private static final int MAX_REDIRECTS = 5; public final String url; private static OkHttpClient okHttpClient = new OkHttpClient(); private Call requestCall = null; private InputStream inputStream; private volatile int length = Integer.MIN_VALUE; private volatile String mime; private Mapheaders; public HttpUrlSource(String url) { this(url, ProxyCacheUtils.getSupposablyMime(url)); } public HttpUrlSource(String url, Map headers) { this(url, ProxyCacheUtils.getSupposablyMime(url)); this.headers = headers; } public HttpUrlSource(String url, String mime) { this.url = Preconditions.checkNotNull(url); this.mime = mime; } public HttpUrlSource(HttpUrlSource source) { this.url = source.url; this.mime = source.mime; this.length = source.length; } @Override public synchronized int length() throws ProxyCacheException { if (length == Integer.MIN_VALUE) { fetchContentInfo(); } return length; } @Override public void open(int offset) throws ProxyCacheException { try { Response response = openConnection(offset, -1); mime = response.header("Content-Type"); inputStream = new BufferedInputStream(response.body().byteStream(), DEFAULT_BUFFER_SIZE); length = readSourceAvailableBytes(response, offset, response.code()); } catch (IOException e) { throw new ProxyCacheException("Error opening okHttpClient for " + url + " with offset " + offset, e); } } private int readSourceAvailableBytes(Response response, int offset, int responseCode) throws IOException { int contentLength = Integer.valueOf(response.header("Content-Length", "-1")); return responseCode == HTTP_OK ? contentLength : responseCode == HTTP_PARTIAL ? contentLength + offset : length; } @Override public void close() throws ProxyCacheException { if (okHttpClient != null && inputStream != null && requestCall != null) { try { inputStream.close(); requestCall.cancel(); } catch (IOException e) { e.printStackTrace(); } } } @Override public int read(byte[] buffer) throws ProxyCacheException { if (inputStream == null) { throw new ProxyCacheException("Error reading data from " + url + ": okHttpClient is absent!"); } try { return inputStream.read(buffer, 0, buffer.length); } catch (InterruptedIOException e) { throw new InterruptedProxyCacheException("Reading source " + url + " is interrupted", e); } catch (IOException e) { throw new ProxyCacheException("Error reading data from " + url, e); } } private void fetchContentInfo() throws ProxyCacheException { MyLog.d(LOG_TAG, "Read content info from " + url); Response response = null; InputStream inputStream = null; try { response = openConnection(0, 20000); length = Integer.valueOf(response.header("Content-Length", "-1")); mime = response.header("Content-Type"); inputStream = response.body().byteStream(); MyLog.i(LOG_TAG, "Content info for `" + url + "`: mime: " + mime + ", content-length: " + length); } catch (IOException e) { MyLog.e(LOG_TAG, "Error fetching info from " + url, e); } finally { ProxyCacheUtils.close(inputStream); if (response != null) { requestCall.cancel(); } } } private Response openConnection(int offset, int timeout) throws IOException, ProxyCacheException { boolean redirected; int redirectCount = 0; String url = this.url; Request request = null; //do { MyLog.d(LOG_TAG, "Open okHttpClient " + (offset > 0 ? " with offset " + offset : "") + " to " + url); // okHttpClient = (HttpURLConnection) new URL(url).openConnection(); Request.Builder builder = new Request.Builder(); builder.url(url); //flac if(headers != null) { //设置请求头 for (Map.Entry entry : headers.entrySet()) { MyLog.i(LOG_TAG, "请求头信息 key:" + entry.getKey() +" Value" + entry.getValue()); // okHttpClient.setRequestProperty(entry.getKey(), entry.getValue()); builder.addHeader(entry.getKey(), entry.getValue()); } } if (offset > 0) { builder.addHeader("Range", "bytes=" + offset + "-"); } request = builder.build(); requestCall = okHttpClient.newCall(request); /*if (redirected) { url = okHttpClient.getHeaderField("Location"); redirectCount++; okHttpClient.disconnect(); } if (redirectCount > MAX_REDIRECTS) { throw new ProxyCacheException("Too many redirects: " + redirectCount); }*/ //} while (redirected); return requestCall.execute(); } public synchronized String getMime() throws ProxyCacheException { if (TextUtils.isEmpty(mime)) { fetchContentInfo(); } return mime; } public String getUrl() { return url; } @Override public String toString() { return "HttpUrlSource{url='" + url + "}"; } }
以上是“Android视频/音频缓存框架AndroidVideoCache怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!