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,Map headers){ 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.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){ 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。