下面是要實現的效果
。
這個demo,主要實現的功能有:多線程上傳,斷點續傳, Notification的使用。多線程下載的主要原理是,對要下載的文件進行分割,每個線程取一個獨立的區域進行下載。
URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("GET");
//startIndex和endIndex表示當前需要下載的文件的開始和結束的字節 conn.setRequestProperty("Range", "bytes="+startIndex+""+endIndex);
寫入的時候是通過java的RandomAccessFile 類來獲取寫入的開始位置,獲取了開始的位置后,由於已經對服務器的文件大小進行了分割,依次寫入流文件即可。
對於單線程情況下的斷點續傳,一般情況下是通過計算已經下載的文件的大小,然后從末尾處選擇開始下載。多線程情況下,感覺應該是對於每個線程下的位置進行記錄,然后從記錄的位置開始下載。
本文並沒有從頭到尾寫一個這樣的過程,android開源框架Xutils提供了這一整套的類庫和方法,github地址是https://github.com/wyouflf/xUtils。使用該類庫需要網絡和讀寫SD卡的權限,
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
下面呈現核心的代碼。布局文件只有一個按鈕沒什么好說的。首先初始化這樣一些變量:
int id =1; private Button mButton; private NotificationManager mNotifyManager; NotificationCompat.Builder mBuilder ;
然后在onCreate方法中,對它們進行初始化。
mButton = (Button) findViewById(R.id.id_bt_startNotificationDownload); mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mBuilder = new NotificationCompat.Builder(this); mBuilder.setContentTitle("內容下載").setContentText("下載中,請騷等").setSmallIcon(R.drawable.notification);
//點擊按鈕,開始下載
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
download("https://github.com/wyouflf/xCombine/archive/master.zip",
"/sdcard/xCombine_master.zip");
}
});
下面是使用Xutil的類庫進行多線程下載的方法。
private void download(String url, String filePath){ HttpUtils httpUtils = new HttpUtils(); //可以設置線程池的大小,下載充實的次數,超時時間等等。 HttpHandler hanlder = httpUtils.configRequestThreadPoolSize(5).download(url, filePath, true, true, new RequestCallBack<File>() { @Override public void onSuccess(ResponseInfo<File> responseInfo) { //成功后將setProgress的兩個變量設置為0,progress就會消失。setProgerss第三個參數的含義是,如果能確定進度條執行的時間,就傳入true,否則是false,此處直接傳入false即可。 mBuilder.setProgress(0, 0,false).setContentText("已經下載完成"); mNotifyManager.notify(id, mBuilder.build()); } @Override public void onFailure(HttpException e, String s) { //失敗后執行的方法 Toast.makeText(MainActivity.this,"fali , try again",Toast.LENGTH_LONG).show(); } @Override public void onStart() { //開始時候,初始化進度條 mBuilder.setProgress(100, 0,false); mNotifyManager.notify(id, mBuilder.build()); } @Override public void onLoading(long total, long current, boolean isUploading) { //更新進度條 int currentNum = (int) (100*current/total); mBuilder.setProgress(100, currentNum,false); mNotifyManager.notify(id, mBuilder.build()); } }); }