Android视频/音频缓存框架AndroidVideoCache(Okhttp)详解
关于安卓边下边播功能,供大家参考,具体内容如下
对于视频/音频软件,音乐软件,视频软件,都有缓存这个功能,那如何实现边下边播功能:
- 如何实现这个边下边播功能?
- 文件是否支持同时读写?(Mediaplayer播放文件,从网络上下载文件)
- 播放与下载进度如何协调?
- 已缓存的文件需及时清理
经过一番折腾,我find了:[AndroidVideoCache],这个库是danikula大神写,看完源码后收益匪浅。实现流媒体边下边播原理利用socket开启一个本机的代理服务器
结合自身需求,修改了该库,使用okhttp进行网络请求:
AndroidVideoCache(改成okhttp缓存)
packagecom.danikula.videocache;
importandroid.text.TextUtils;
importjava.io.BufferedInputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InterruptedIOException;
importjava.util.Map;
importjava.util.concurrent.TimeUnit;
importcom.danikula.videocache.file.MyLog;
importokhttp3.Call;
importokhttp3.OkHttpClient;
importokhttp3.Request;
importokhttp3.Response;
importstaticcom.danikula.videocache.ProxyCacheUtils.DEFAULT_BUFFER_SIZE;
importstaticcom.danikula.videocache.ProxyCacheUtils.LOG_TAG;
importstaticjava.net.HttpURLConnection.HTTP_OK;
importstaticjava.net.HttpURLConnection.HTTP_PARTIAL;
/**
*{@linkSource}thatuseshttpresourceassourcefor{@linkProxyCache}.
*
*@authorAlexeyDanilov(danikula@gmail.com).
*
*从URL获取数据
*/
publicclassHttpUrlSourceimplementsSource{
privatestaticfinalintMAX_REDIRECTS=5;
publicfinalStringurl;
privatestaticOkHttpClientokHttpClient=newOkHttpClient();
privateCallrequestCall=null;
privateInputStreaminputStream;
privatevolatileintlength=Integer.MIN_VALUE;
privatevolatileStringmime;
privateMapheaders;
publicHttpUrlSource(Stringurl){
this(url,ProxyCacheUtils.getSupposablyMime(url));
}
publicHttpUrlSource(Stringurl,Mapheaders){
this(url,ProxyCacheUtils.getSupposablyMime(url));
this.headers=headers;
}
publicHttpUrlSource(Stringurl,Stringmime){
this.url=Preconditions.checkNotNull(url);
this.mime=mime;
}
publicHttpUrlSource(HttpUrlSourcesource){
this.url=source.url;
this.mime=source.mime;
this.length=source.length;
}
@Override
publicsynchronizedintlength()throwsProxyCacheException{
if(length==Integer.MIN_VALUE){
fetchContentInfo();
}
returnlength;
}
@Override
publicvoidopen(intoffset)throwsProxyCacheException{
try{
Responseresponse=openConnection(offset,-1);
mime=response.header("Content-Type");
inputStream=newBufferedInputStream(response.body().byteStream(),DEFAULT_BUFFER_SIZE);
length=readSourceAvailableBytes(response,offset,response.code());
}catch(IOExceptione){
thrownewProxyCacheException("ErroropeningokHttpClientfor"+url+"withoffset"+offset,e);
}
}
privateintreadSourceAvailableBytes(Responseresponse,intoffset,intresponseCode)throwsIOException{
intcontentLength=Integer.valueOf(response.header("Content-Length","-1"));
returnresponseCode==HTTP_OK?contentLength
:responseCode==HTTP_PARTIAL?contentLength+offset:length;
}
@Override
publicvoidclose()throwsProxyCacheException{
if(okHttpClient!=null&&inputStream!=null&&requestCall!=null){
try{
inputStream.close();
requestCall.cancel();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
@Override
publicintread(byte[]buffer)throwsProxyCacheException{
if(inputStream==null){
thrownewProxyCacheException("Errorreadingdatafrom"+url+":okHttpClientisabsent!");
}
try{
returninputStream.read(buffer,0,buffer.length);
}catch(InterruptedIOExceptione){
thrownewInterruptedProxyCacheException("Readingsource"+url+"isinterrupted",e);
}catch(IOExceptione){
thrownewProxyCacheException("Errorreadingdatafrom"+url,e);
}
}
privatevoidfetchContentInfo()throwsProxyCacheException{
MyLog.d(LOG_TAG,"Readcontentinfofrom"+url);
Responseresponse=null;
InputStreaminputStream=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,"Contentinfofor`"+url+"`:mime:"+mime+",content-length:"+length);
}catch(IOExceptione){
MyLog.e(LOG_TAG,"Errorfetchinginfofrom"+url,e);
}finally{
ProxyCacheUtils.close(inputStream);
if(response!=null){
requestCall.cancel();
}
}
}
privateResponseopenConnection(intoffset,inttimeout)throwsIOException,ProxyCacheException{
booleanredirected;
intredirectCount=0;
Stringurl=this.url;
Requestrequest=null;
//do{
MyLog.d(LOG_TAG,"OpenokHttpClient"+(offset>0?"withoffset"+offset:"")+"to"+url);
//okHttpClient=(HttpURLConnection)newURL(url).openConnection();
Request.Builderbuilder=newRequest.Builder();
builder.url(url);
//flac
if(headers!=null){
//设置请求头
for(Map.Entryentry: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){
thrownewProxyCacheException("Toomanyredirects:"+redirectCount);
}*/
//}while(redirected);
returnrequestCall.execute();
}
publicsynchronizedStringgetMime()throwsProxyCacheException{
if(TextUtils.isEmpty(mime)){
fetchContentInfo();
}
returnmime;
}
publicStringgetUrl(){
returnurl;
}
@Override
publicStringtoString(){
return"HttpUrlSource{url='"+url+"}";
}
}
下载地址:Android视频音频缓存框架AndroidVideoCache
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。