Android下載-實時進度-斷點續傳
概述
帶顯示進度和斷點續傳的下載示例
使用Okhttp框架
思路
獲取下載檔案的總大小,獲取本地檔案,如果不存在,就下載,存在,就獲取檔案的大小,
如果本地檔案的大小與網路上檔案的大小,就提示下載完成。
如果本地檔案大小 < 網路上檔案的大小,就跳過已下載的位元組數開始下載。
具體實現
file = new File(path);
if (file.exists()){
downloadedLength = file.length();
}
//獲取下載檔案的總長度
long contentLength = getContentLength(url);
if (contentLength == 0 ){
//獲取網路檔案大小失敗.
}else if (contentLength == downloadedLength){
//下載完成.
}
獲取網路檔案大小
public static long getContentLength(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
if (response != null && response.isSuccessful()){
long contentLength = response.body().contentLength();
response.close();
return contentLength;
}
return 0;
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
//斷點下載,跳過已下載的位元組
.addHeader("RANGE", "bytes=" + downloadedLength + "-")
.url(url)
.build();
//執行同步請求
Response response = client.newCall(request).execute();
if (response != null){
inputStream = response.body().byteStream();
saveFile = new RandomAccessFile(file, "rw");
saveFile.seek(downloadedLength); //儲存檔案時跳過已下載的位元組
byte[] b = new byte[1024];
int total = 0;
int len;
while ((len = inputStream.read(b)) != -1){
total += len;
saveFile.write(b,0,len);
int progress = (int)((total + downloadedLength) * 100 / contentLength);//progress代表百分比
publishProgress(progress);//呼叫onProgressUpdate()更新進度條
}
response.body().close();
}
RandomAccessFile類
RandomAccessFile是用來訪問那些儲存資料記錄的檔案的,你就可以用seek( )方法來訪問記錄,並進行讀寫了。這些記錄的大小不必相同;但是其大小和位置必須是可知的。但是該類僅限於操作檔案。
RandomAccessFile不屬於InputStream和OutputStream類系的。實際上,除了實現DataInput和DataOutput介面之外(DataInputStream和DataOutputStream也實現了這兩個介面),它和這兩個類系毫不相干,甚至不使用InputStream和OutputStream類中已經存在的任何功能;它是一個完全獨立的類,所有方法(絕大多數都只屬於它自己)都是從零開始寫的。這可能是因為RandomAccessFile能在檔案裡面前後移動,所以它的行為與其它的I/O類有些根本性的不同。總而言之,它是一個直接繼承Object的,獨立的類。
基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream結合起來,再加上它自己的一些方法,比如定位用的getFilePointer( ),在檔案裡移動用的seek( ),以及判斷檔案大小的length( )、skipBytes()跳過多少位元組數。此外,它的建構函式還要一個表示以只讀方式(“r”),還是以讀寫方式(“rw”)開啟檔案的引數 (和C的fopen( )一模一樣)。它不支援只寫檔案。