
game.gif
Android部分代碼
所有下載線程的信息會存儲再hashmap中,但是這個是線程不安全的。不過我們只是用來存一些數(shù)據(jù)用來返回給前端進度。
/**
* 當前下載對象
* {
* key: name 線程名
* value : {
* key:filelength 文件總大小
* key:state 文件狀態(tài)
* key:haveDownloaded 當前下載量
* }
* }
*/
public Map<String, Plan> planMap = new HashMap<>();
每次請求會創(chuàng)建一個線程進行下載,代碼每次寫入會有一定的性能損失,可以先緩存部分然后再一次性寫入。
/**
* 下載文件
*
* @param uri 下載地址
* @throws Exception
*/
@JavascriptInterface
public void downLoad(String uri) throws Exception {
Plan verify = planMap.get(getFileName(uri));
if (verify == null || (!verify.state && verify.haveDownloaded < verify.filelength)) {
new Thread() {//子線程
public void run() {
try {
//獲取服務器上文件的大小
HttpClient client = new DefaultHttpClient();
HttpHead request = new HttpHead(uri);
HttpResponse response = client.execute(request);
//response 只有響應頭 沒有響應體
if (response.getStatusLine().getStatusCode() == 200) {
Header[] headers = response.getHeaders("Content-Length");
String value = headers[0].getValue();
//文件大小
Long filelength = Long.parseLong(value);
Log.i("下載文件", "filelength:" + filelength);
//在sdcard創(chuàng)建和服務器大小一樣的文件
String name = getFileName(uri);
File file = new File("/data/data/" + mContext.getPackageName() + "/files", name + ".downLoad");
if ((file.exists() && file.length() < filelength) || !file.exists()) {
//隨機訪問文件
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//修改下載的開始位置 重新下載
Long start = file.length();
HttpGet httpget = new HttpGet(uri);
httpget.addHeader("Range", "bytes=" + start + "-");//添加請求頭
response = client.execute(httpget);
InputStream inputStream = response.getEntity().getContent();
//跳轉(zhuǎn)到起始位置
raf.seek(start);
//把流寫入到文件
byte[] buffer = new byte[65536];
int len = 0;
Plan plan = planMap.get(getFileName(uri));
if (plan == null)
plan = new Plan();
plan.filelength = filelength;
plan.haveDownloaded = start;
plan.state = true;
planMap.put(name, plan);//當前線程數(shù)據(jù)更新
/*更新下載文件列表*/
updateFiles();
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1 && plan.state) {
//寫數(shù)據(jù)
raf.write(buffer, 0, len);
plan.haveDownloaded += len;//當前下載數(shù)
//模擬 看到進度條動的效果
// SystemClock.sleep(50);
}
httpget.releaseConnection();
inputStream.close();
//關(guān)閉
raf.close();
if (file.length() == filelength) {
file.renameTo(new File("/data/data/" + mContext.getPackageName() + "/files", name));
/*更新下載文件列表*/
updateFiles();
}
Log.i("下載", name + "下載結(jié)束");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
;
}.start();
}
}
一個用到的實體類,用來傳給前端當前下載的信息
class Plan {
/**
* 總大小
*/
Long filelength;
/**
* 代表當前線程狀態(tài) true進行中 false 暫停
*/
Boolean state;
/**
* 當前已下載的數(shù)據(jù)量
*/
long haveDownloaded;
}
updateFiles這個方法是用來讀取當前目錄下的文件用的,有g(shù)etFiles的方法給前端調(diào)用,
作用是 重啟APP后獲取下載記錄。
代碼就不貼上來了。
所有代碼只提供參考思路,拒絕縫合怪