Android中實現可暫停的斷點續傳的下載

今天學習了Android開發中比較難的一個環節,就是斷點續傳下載,不少人看到這個標題就感受頭大,的確,若是沒有良好的邏輯思惟,這塊的確很難搞明白。下面我就將本身學到的知識和一些看法寫下供那些在這個環節還煩惱的人蔘考。這裏我如下載mp3文件爲例。 java

斷點續傳下載,顧名思義,那就是咱們在一次下載未結束時,退出下載,第二次下載時會接着第一次下載的進度繼續下載。那麼怎麼記錄第一次下載的數據呢,這裏確定就要用到數據庫了。下面就是我建立數據庫的一個SQLiteOpenHelper類。用來首次運行時建立數據庫。 android

DBHelper類: sql

  1. 1 package cn.yj3g.DBHelper;  
  2.  2  
  3.  3 import android.content.Context;  
  4.  4 import android.database.sqlite.SQLiteDatabase;  
  5.  5 import android.database.sqlite.SQLiteOpenHelper;  
  6.  6  
  7.  7     /** 
  8.  8      * 創建一個數據庫幫助類 
  9.  9      */  
  10. 10 public class DBHelper extends SQLiteOpenHelper {  
  11. 11     //download.db-->數據庫名  
  12. 12     public DBHelper(Context context) {  
  13. 13         super(context, "download.db"null1);  
  14. 14     }  
  15. 15      
  16. 16     /** 
  17. 17      * 在download.db數據庫下建立一個download_info表存儲下載信息 
  18. 18      */  
  19. 19     @Override  
  20. 20     public void onCreate(SQLiteDatabase db) {  
  21. 21         db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "  
  22. 22                 + "start_pos integer, end_pos integer, compelete_size integer,url char)");  
  23. 23     }  
  24. 24     @Override  
  25. 25     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  26. 26  
  27. 27     }  
  28. 28  
  29. 29 }  

1 package cn.yj3g.DBHelper;
 2
 3 import android.content.Context;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.database.sqlite.SQLiteOpenHelper;
 6
 7     /**
 8      * 創建一個數據庫幫助類
 9      */
10 public class DBHelper extends SQLiteOpenHelper {
11     //download.db-->數據庫名
12     public DBHelper(Context context) {
13         super(context, "download.db", null, 1);
14     }
15    
16     /**
17      * 在download.db數據庫下建立一個download_info表存儲下載信息
18      */
19     @Override
20     public void onCreate(SQLiteDatabase db) {
21         db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "
22                 + "start_pos integer, end_pos integer, compelete_size integer,url char)");
23     }
24     @Override
25     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
26
27     }
28
29 }

下面來看主界面的佈局,在這裏,我只設計了一個ListView來顯示下載的音樂的名稱,和一個開始下載按鈕和一個暫停按鈕。 數據庫

佈局文件以下: 數組

main.xml: 網絡

  1. 1 <?xml version="1.0" encoding="utf-8"?>  
  2.  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.  3     android:orientation="vertical"  
  4.  4     android:layout_width="fill_parent"  
  5.  5     android:layout_height="fill_parent"  
  6.  6     android:id="@+id/llRoot">  
  7.  7     <ListView android:id="@android :id/list"  
  8.  8         android:layout_width="fill_parent"  
  9.  9         android:layout_height="fill_parent">  
  10. 10     </ListView>  
  11. 11 </LinearLayout>  

1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical"
 4     android:layout_width="fill_parent"
 5     android:layout_height="fill_parent"
 6     android:id="@+id/llRoot">
 7     <ListView android:id="@android:id/list"
 8         android:layout_width="fill_parent"
 9         android:layout_height="fill_parent">
10     </ListView>
11 </LinearLayout>

list_item.xml: app

  1. 1 <?xml version="1.0" encoding="utf-8"?>  
  2.  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.  3            android:orientation="vertical"  
  4.  4            android:layout_width="fill_parent"  
  5.  5            android:layout_height="wrap_content">  
  6.  6     <LinearLayout  
  7.  7            android:orientation="horizontal"  
  8.  8            android:layout_width="fill_parent"  
  9.  9            android:layout_height="wrap_content"  
  10. 10            android:layout_marginBottom="5dip">  
  11. 11         <TextView  
  12. 12             android:layout_width="fill_parent"  
  13. 13             android:layout_height="wrap_content"  
  14. 14             android:layout_weight="1"  
  15. 15             android:id="@+id/tv_resouce_name"/>  
  16. 16         <Button  
  17. 17             android:layout_width="fill_parent"  
  18. 18             android:layout_height="wrap_content"  
  19. 19             android:layout_weight="1"  
  20. 20             android:text="下載"  
  21. 21             android:id="@+id/btn_start"  
  22. 22             android:onClick="startDownload"/>  
  23. 23         <Button  
  24. 24             android:layout_width="fill_parent"  
  25. 25             android:layout_height="wrap_content"  
  26. 26             android:layout_weight="1"  
  27. 27             android:text="暫停"  
  28. 28             android:id="@+id/btn_pause"  
  29. 29             android:onClick="pauseDownload"/>  
  30. 30       </LinearLayout>  
  31. 31 </LinearLayout>  

1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3            android:orientation="vertical"
 4            android:layout_width="fill_parent"
 5            android:layout_height="wrap_content">
 6     <LinearLayout
 7            android:orientation="horizontal"
 8            android:layout_width="fill_parent"
 9            android:layout_height="wrap_content"
10            android:layout_marginBottom="5dip">
11         <TextView
12             android:layout_width="fill_parent"
13             android:layout_height="wrap_content"
14             android:layout_weight="1"
15             android:id="@+id/tv_resouce_name"/>
16         <Button
17             android:layout_width="fill_parent"
18             android:layout_height="wrap_content"
19             android:layout_weight="1"
20             android:text="下載"
21             android:id="@+id/btn_start"
22             android:onClick="startDownload"/>
23         <Button
24             android:layout_width="fill_parent"
25             android:layout_height="wrap_content"
26             android:layout_weight="1"
27             android:text="暫停"
28             android:id="@+id/btn_pause"
29             android:onClick="pauseDownload"/>
30       </LinearLayout>
31 </LinearLayout>

主界面運行效果以下: dom

下面咱們來看具體實現下載的方法。首先,咱們要定義一個記錄在下載時各個時期的數據的類,這裏我建立了一個DownloadInfo類來記錄。代碼以下: ide

DownloadInfo: 工具

  1. 1 package cn.yj3g.entity;  
  2.  2 /** 
  3.  3  *建立一個下載信息的實體類 
  4.  4  */  
  5.  5 public class DownloadInfo {  
  6.  6     private int threadId;//下載器id  
  7.  7     private int startPos;//開始點  
  8.  8     private int endPos;//結束點  
  9.  9     private int compeleteSize;//完成度  
  10. 10     private String url;//下載器網絡標識  
  11. 11     public DownloadInfo(int threadId, int startPos, int endPos,  
  12. 12             int compeleteSize,String url) {  
  13. 13         this.threadId = threadId;  
  14. 14         this.startPos = startPos;  
  15. 15         this.endPos = endPos;  
  16. 16         this.compeleteSize = compeleteSize;  
  17. 17         this.url=url;  
  18. 18     }  
  19. 19     public DownloadInfo() {  
  20. 20     }  
  21. 21     public String getUrl() {  
  22. 22         return url;  
  23. 23     }  
  24. 24     public void setUrl(String url) {  
  25. 25         this.url = url;  
  26. 26     }  
  27. 27     public int getThreadId() {  
  28. 28         return threadId;  
  29. 29     }  
  30. 30     public void setThreadId(int threadId) {  
  31. 31         this.threadId = threadId;  
  32. 32     }  
  33. 33     public int getStartPos() {  
  34. 34         return startPos;  
  35. 35     }  
  36. 36     public void setStartPos(int startPos) {  
  37. 37         this.startPos = startPos;  
  38. 38     }  
  39. 39     public int getEndPos() {  
  40. 40         return endPos;  
  41. 41     }  
  42. 42     public void setEndPos(int endPos) {  
  43. 43         this.endPos = endPos;  
  44. 44     }  
  45. 45     public int getCompeleteSize() {  
  46. 46         return compeleteSize;  
  47. 47     }  
  48. 48     public void setCompeleteSize(int compeleteSize) {  
  49. 49         this.compeleteSize = compeleteSize;  
  50. 50     }  
  51. 51  
  52. 52     @Override  
  53. 53     public String toString() {  
  54. 54         return "DownloadInfo [threadId=" + threadId  
  55. 55                 + ", startPos=" + startPos + ", endPos=" + endPos  
  56. 56                 + ", compeleteSize=" + compeleteSize +"]";  
  57. 57     }  
  58. 58 }  

1 package cn.yj3g.entity;
 2 /**
 3  *建立一個下載信息的實體類
 4  */
 5 public class DownloadInfo {
 6     private int threadId;//下載器id
 7     private int startPos;//開始點
 8     private int endPos;//結束點
 9     private int compeleteSize;//完成度
10     private String url;//下載器網絡標識
11     public DownloadInfo(int threadId, int startPos, int endPos,
12             int compeleteSize,String url) {
13         this.threadId = threadId;
14         this.startPos = startPos;
15         this.endPos = endPos;
16         this.compeleteSize = compeleteSize;
17         this.url=url;
18     }
19     public DownloadInfo() {
20     }
21     public String getUrl() {
22         return url;
23     }
24     public void setUrl(String url) {
25         this.url = url;
26     }
27     public int getThreadId() {
28         return threadId;
29     }
30     public void setThreadId(int threadId) {
31         this.threadId = threadId;
32     }
33     public int getStartPos() {
34         return startPos;
35     }
36     public void setStartPos(int startPos) {
37         this.startPos = startPos;
38     }
39     public int getEndPos() {
40         return endPos;
41     }
42     public void setEndPos(int endPos) {
43         this.endPos = endPos;
44     }
45     public int getCompeleteSize() {
46         return compeleteSize;
47     }
48     public void setCompeleteSize(int compeleteSize) {
49         this.compeleteSize = compeleteSize;
50     }
51
52     @Override
53     public String toString() {
54         return "DownloadInfo [threadId=" + threadId
55                 + ", startPos=" + startPos + ", endPos=" + endPos
56                 + ", compeleteSize=" + compeleteSize +"]";
57     }
58 }

在下載時,咱們有進度條來顯示進度,怎麼肯定進度條的進度,大小和起始位置呢?這裏我定義了一個LoadInfo類來記錄下載器詳細信息。代碼以下:

LoadInfo:

  1. 1 package cn.yj3g.entity;  
  2.  2 /** 
  3.  3  *自定義的一個記載下載器詳細信息的類 
  4.  4  */  
  5.  5 public class LoadInfo {  
  6.  6     public int fileSize;//文件大小  
  7.  7     private int complete;//完成度  
  8.  8     private String urlstring;//下載器標識  
  9.  9     public LoadInfo(int fileSize, int complete, String urlstring) {  
  10. 10         this.fileSize = fileSize;  
  11. 11         this.complete = complete;  
  12. 12         this.urlstring = urlstring;  
  13. 13     }  
  14. 14     public LoadInfo() {  
  15. 15     }  
  16. 16     public int getFileSize() {  
  17. 17         return fileSize;  
  18. 18     }  
  19. 19     public void setFileSize(int fileSize) {  
  20. 20         this.fileSize = fileSize;  
  21. 21     }  
  22. 22     public int getComplete() {  
  23. 23         return complete;  
  24. 24     }  
  25. 25     public void setComplete(int complete) {  
  26. 26         this.complete = complete;  
  27. 27     }  
  28. 28     public String getUrlstring() {  
  29. 29         return urlstring;  
  30. 30     }  
  31. 31     public void setUrlstring(String urlstring) {  
  32. 32         this.urlstring = urlstring;  
  33. 33     }  
  34. 34     @Override  
  35. 35     public String toString() {  
  36. 36         return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete  
  37. 37                 + ", urlstring=" + urlstring + "]";  
  38. 38     }  
  39. 39 }  

1 package cn.yj3g.entity;
 2 /**
 3  *自定義的一個記載下載器詳細信息的類
 4  */
 5 public class LoadInfo {
 6     public int fileSize;//文件大小
 7     private int complete;//完成度
 8     private String urlstring;//下載器標識
 9     public LoadInfo(int fileSize, int complete, String urlstring) {
10         this.fileSize = fileSize;
11         this.complete = complete;
12         this.urlstring = urlstring;
13     }
14     public LoadInfo() {
15     }
16     public int getFileSize() {
17         return fileSize;
18     }
19     public void setFileSize(int fileSize) {
20         this.fileSize = fileSize;
21     }
22     public int getComplete() {
23         return complete;
24     }
25     public void setComplete(int complete) {
26         this.complete = complete;
27     }
28     public String getUrlstring() {
29         return urlstring;
30     }
31     public void setUrlstring(String urlstring) {
32         this.urlstring = urlstring;
33     }
34     @Override
35     public String toString() {
36         return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete
37                 + ", urlstring=" + urlstring + "]";
38     }
39 }

下面是最最重要的一步,那就是定義一個下載器來進行下載了,這裏我就很少說,具體解釋在代碼中都有註解,我就直接將代碼附下,供你們研究參考

Downloader:

  1.  1 package cn.yj3g.service;  
  2.   2  
  3.   3 import java.io.File;  
  4.   4 import java.io.InputStream;  
  5.   5 import java.io.RandomAccessFile;  
  6.   6 import java.net.HttpURLConnection;  
  7.   7 import java.net.URL;  
  8.   8 import java.util.ArrayList;  
  9.   9 import java.util.List;  
  10.  10 import android.content.Context;  
  11.  11 import android.os.Handler;  
  12.  12 import android.os.Message;  
  13.  13 import android.util.Log;  
  14.  14 import cn.yj3g.Dao.Dao;  
  15.  15 import cn.yj3g.entity.DownloadInfo;  
  16.  16 import cn.yj3g.entity.LoadInfo;  
  17.  17  
  18.  18 public class Downloader {  
  19.  19     private String urlstr;// 下載的地址  
  20.  20     private String localfile;// 保存路徑  
  21.  21     private int threadcount;// 線程數  
  22.  22     private Handler mHandler;// 消息處理器  
  23.  23     private Dao dao;// 工具類  
  24.  24     private int fileSize;// 所要下載的文件的大小  
  25.  25     private List<DownloadInfo> infos;// 存放下載信息類的集合  
  26.  26     private static final int INIT = 1;//定義三種下載的狀態:初始化狀態,正在下載狀態,暫停狀態  
  27.  27     private static final int DOWNLOADING = 2;  
  28.  28     private static final int PAUSE = 3;  
  29.  29     private int state = INIT;  
  30.  30  
  31.  31     public Downloader(String urlstr, String localfile, int threadcount,  
  32.  32             Context context, Handler mHandler) {  
  33.  33         this.urlstr = urlstr;  
  34.  34         this.localfile = localfile;  
  35.  35         this.threadcount = threadcount;  
  36.  36         this.mHandler = mHandler;  
  37.  37         dao = new Dao(context);  
  38.  38     }  
  39.  39     /** 
  40.  40      *判斷是否正在下載 
  41.  41      */  
  42.  42     public boolean isdownloading() {  
  43.  43         return state == DOWNLOADING;  
  44.  44     }  
  45.  45     /** 
  46.  46      * 獲得downloader裏的信息 
  47.  47      * 首先進行判斷是不是第一次下載,若是是第一次就要進行初始化,並將下載器的信息保存到數據庫中 
  48.  48      * 若是不是第一次下載,那就要從數據庫中讀出以前下載的信息(起始位置,結束爲止,文件大小等),並將下載信息返回給下載器 
  49.  49      */  
  50.  50     public LoadInfo getDownloaderInfors() {  
  51.  51         if (isFirst(urlstr)) {  
  52.  52             Log.v("TAG""isFirst");  
  53.  53             init();  
  54.  54             int range = fileSize / threadcount;  
  55.  55             infos = new ArrayList<DownloadInfo>();  
  56.  56             for (int i = 0; i < threadcount - 1; i++) {  
  57.  57                 DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 10, urlstr);  
  58.  58                 infos.add(info);  
  59.  59             }  
  60.  60             DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 10, urlstr);  
  61.  61             infos.add(info);  
  62.  62             //保存infos中的數據到數據庫  
  63.  63             dao.saveInfos(infos);  
  64.  64             //建立一個LoadInfo對象記載下載器的具體信息  
  65.  65             LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);  
  66.  66             return loadInfo;  
  67.  67         } else {  
  68.  68             //獲得數據庫中已有的urlstr的下載器的具體信息  
  69.  69             infos = dao.getInfos(urlstr);  
  70.  70             Log.v("TAG""not isFirst size=" + infos.size());  
  71.  71             int size = 0;  
  72.  72             int compeleteSize = 0;  
  73.  73             for (DownloadInfo info : infos) {  
  74.  74                 compeleteSize += info.getCompeleteSize();  
  75.  75                 size += info.getEndPos() - info.getStartPos() + 1;  
  76.  76             }  
  77.  77             return new LoadInfo(size, compeleteSize, urlstr);  
  78.  78         }  
  79.  79     }  
  80.  80  
  81.  81     /** 
  82.  82      * 初始化 
  83.  83      */  
  84.  84     private void init() {  
  85.  85         try {  
  86.  86             URL url = new URL(urlstr);  
  87.  87             HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  88.  88             connection.setConnectTimeout(5000);  
  89.  89             connection.setRequestMethod("GET");  
  90.  90             fileSize = connection.getContentLength();  
  91.  91  
  92.  92             File file = new File(localfile);  
  93.  93             if (!file.exists()) {  
  94.  94                 file.createNewFile();  
  95.  95             }  
  96.  96             // 本地訪問文件  
  97.  97             RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");  
  98.  98             accessFile.setLength(fileSize);  
  99.  99             accessFile.close();  
  100. 100             connection.disconnect();  
  101. 101         } catch (Exception e) {  
  102. 102             e.printStackTrace();  
  103. 103         }  
  104. 104     }  
  105. 105  
  106. 106     /** 
  107. 107      * 判斷是不是第一次 下載 
  108. 108      */  
  109. 109     private boolean isFirst(String urlstr) {  
  110. 110         return dao.isHasInfors(urlstr);  
  111. 111     }  
  112. 112  
  113. 113     /** 
  114. 114      * 利用線程開始下載數據 
  115. 115      */  
  116. 116     public void download() {  
  117. 117         if (infos != null) {  
  118. 118             if (state == DOWNLOADING)  
  119. 119                 return;  
  120. 120             state = DOWNLOADING;  
  121. 121             for (DownloadInfo info : infos) {  
  122. 122                 new MyThread(info.getThreadId(), info.getStartPos(),  
  123. 123                         info.getEndPos(), info.getCompeleteSize(),  
  124. 124                         info.getUrl()).start();  
  125. 125             }  
  126. 126         }  
  127. 127     }  
  128. 128  
  129. 129     public class MyThread extends Thread {  
  130. 130         private int threadId;  
  131. 131         private int startPos;  
  132. 132         private int endPos;  
  133. 133         private int compeleteSize;  
  134. 134         private String urlstr;  
  135. 135  
  136. 136         public MyThread(int threadId, int startPos, int endPos,  
  137. 137                 int compeleteSize, String urlstr) {  
  138. 138             this.threadId = threadId;  
  139. 139             this.startPos = startPos;  
  140. 140             this.endPos = endPos;  
  141. 141             this.compeleteSize = compeleteSize;  
  142. 142             this.urlstr = urlstr;  
  143. 143         }  
  144. 144         @Override  
  145. 145         public void run() {  
  146. 146             HttpURLConnection connection = null;  
  147. 147             RandomAccessFile randomAccessFile = null;  
  148. 148             InputStream is = null;  
  149. 149             try {  
  150. 150                 URL url = new URL(urlstr);  
  151. 151                 connection = (HttpURLConnection) url.openConnection();  
  152. 152                 connection.setConnectTimeout(5000);  
  153. 153                 connection.setRequestMethod("GET");  
  154. 154                 // 設置範圍,格式爲Range:bytes x-y;  
  155. 155                 connection.setRequestProperty("Range""bytes="+(startPos + compeleteSize) + "-" + endPos);  
  156. 156  
  157. 157                 randomAccessFile = new RandomAccessFile(localfile, "rwd");  
  158. 158                 randomAccessFile.seek(startPos + compeleteSize);  
  159. 159                 // 將要下載的文件寫到保存在保存路徑下的文件中  
  160. 160                 is = connection.getInputStream();  
  161. 161                 byte[] buffer = new byte[4096];  
  162. 162                 int length = -1;  
  163. 163                 while ((length = is.read(buffer)) != -1) {  
  164. 164                     randomAccessFile.write(buffer, 0, length);  
  165. 165                     compeleteSize += length;  
  166. 166                     // 更新數據庫中的下載信息  
  167. 167                     dao.updataInfos(threadId, compeleteSize, urlstr);  
  168. 168                     // 用消息將下載信息傳給進度條,對進度條進行更新  
  169. 169                     Message message = Message.obtain();  
  170. 170                     message.what = 1;  
  171. 171                     message.obj = urlstr;  
  172. 172                     message.arg1 = length;  
  173. 173                     mHandler.sendMessage(message);  
  174. 174                     if (state == PAUSE) {  
  175. 175                         return;  
  176. 176                     }  
  177. 177                 }  
  178. 178             } catch (Exception e) {  
  179. 179                 e.printStackTrace();  
  180. 180             } finally {  
  181. 181                 try {  
  182. 182                     is.close();  
  183. 183                     randomAccessFile.close();  
  184. 184                     connection.disconnect();  
  185. 185                     dao.closeDb();  
  186. 186                 } catch (Exception e) {  
  187. 187                     e.printStackTrace();  
  188. 188                 }  
  189. 189             }  
  190. 190  
  191. 191         }  
  192. 192     }  
  193. 193     //刪除數據庫中urlstr對應的下載器信息  
  194. 194     public void delete(String urlstr) {  
  195. 195         dao.delete(urlstr);  
  196. 196     }  
  197. 197     //設置暫停  
  198. 198     public void pause() {  
  199. 199         state = PAUSE;  
  200. 200     }  
  201. 201     //重置下載狀態  
  202. 202     public void reset() {  
  203. 203         state = INIT;  
  204. 204     }  
  205. 205 }  

1 package cn.yj3g.service;
  2
  3 import java.io.File;
  4 import java.io.InputStream;
  5 import java.io.RandomAccessFile;
  6 import java.net.HttpURLConnection;
  7 import java.net.URL;
  8 import java.util.ArrayList;
  9 import java.util.List;
 10 import android.content.Context;
 11 import android.os.Handler;
 12 import android.os.Message;
 13 import android.util.Log;
 14 import cn.yj3g.Dao.Dao;
 15 import cn.yj3g.entity.DownloadInfo;
 16 import cn.yj3g.entity.LoadInfo;
 17
 18 public class Downloader {
 19     private String urlstr;// 下載的地址
 20     private String localfile;// 保存路徑
 21     private int threadcount;// 線程數
 22     private Handler mHandler;// 消息處理器
 23     private Dao dao;// 工具類
 24     private int fileSize;// 所要下載的文件的大小
 25     private List<DownloadInfo> infos;// 存放下載信息類的集合
 26     private static final int INIT = 1;//定義三種下載的狀態:初始化狀態,正在下載狀態,暫停狀態
 27     private static final int DOWNLOADING = 2;
 28     private static final int PAUSE = 3;
 29     private int state = INIT;
 30
 31     public Downloader(String urlstr, String localfile, int threadcount,
 32             Context context, Handler mHandler) {
 33         this.urlstr = urlstr;
 34         this.localfile = localfile;
 35         this.threadcount = threadcount;
 36         this.mHandler = mHandler;
 37         dao = new Dao(context);
 38     }
 39     /**
 40      *判斷是否正在下載
 41      */
 42     public boolean isdownloading() {
 43         return state == DOWNLOADING;
 44     }
 45     /**
 46      * 獲得downloader裏的信息
 47      * 首先進行判斷是不是第一次下載,若是是第一次就要進行初始化,並將下載器的信息保存到數據庫中
 48      * 若是不是第一次下載,那就要從數據庫中讀出以前下載的信息(起始位置,結束爲止,文件大小等),並將下載信息返回給下載器
 49      */
 50     public LoadInfo getDownloaderInfors() {
 51         if (isFirst(urlstr)) {
 52             Log.v("TAG", "isFirst");
 53             init();
 54             int range = fileSize / threadcount;
 55             infos = new ArrayList<DownloadInfo>();
 56             for (int i = 0; i < threadcount - 1; i++) {
 57                 DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 1, 0, urlstr);
 58                 infos.add(info);
 59             }
 60             DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 1, 0, urlstr);
 61             infos.add(info);
 62             //保存infos中的數據到數據庫
 63             dao.saveInfos(infos);
 64             //建立一個LoadInfo對象記載下載器的具體信息
 65             LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);
 66             return loadInfo;
 67         } else {
 68             //獲得數據庫中已有的urlstr的下載器的具體信息
 69             infos = dao.getInfos(urlstr);
 70             Log.v("TAG", "not isFirst size=" + infos.size());
 71             int size = 0;
 72             int compeleteSize = 0;
 73             for (DownloadInfo info : infos) {
 74                 compeleteSize += info.getCompeleteSize();
 75                 size += info.getEndPos() - info.getStartPos() + 1;
 76             }
 77             return new LoadInfo(size, compeleteSize, urlstr);
 78         }
 79     }
 80
 81     /**
 82      * 初始化
 83      */
 84     private void init() {
 85         try {
 86             URL url = new URL(urlstr);
 87             HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 88             connection.setConnectTimeout(5000);
 89             connection.setRequestMethod("GET");
 90             fileSize = connection.getContentLength();
 91
 92             File file = new File(localfile);
 93             if (!file.exists()) {
 94                 file.createNewFile();
 95             }
 96             // 本地訪問文件
 97             RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
 98             accessFile.setLength(fileSize);
 99             accessFile.close();
100             connection.disconnect();
101         } catch (Exception e) {
102             e.printStackTrace();
103         }
104     }
105
106     /**
107      * 判斷是不是第一次 下載
108      */
109     private boolean isFirst(String urlstr) {
110         return dao.isHasInfors(urlstr);
111     }
112
113     /**
114      * 利用線程開始下載數據
115      */
116     public void download() {
117         if (infos != null) {
118             if (state == DOWNLOADING)
119                 return;
120             state = DOWNLOADING;
121             for (DownloadInfo info : infos) {
122                 new MyThread(info.getThreadId(), info.getStartPos(),
123                         info.getEndPos(), info.getCompeleteSize(),
124                         info.getUrl()).start();
125             }
126         }
127     }
128
129     public class MyThread extends Thread {
130         private int threadId;
131         private int startPos;
132         private int endPos;
133         private int compeleteSize;
134         private String urlstr;
135
136         public MyThread(int threadId, int startPos, int endPos,
137                 int compeleteSize, String urlstr) {
138             this.threadId = threadId;
139             this.startPos = startPos;
140             this.endPos = endPos;
141             this.compeleteSize = compeleteSize;
142             this.urlstr = urlstr;
143         }
144         @Override
145         public void run() {
146             HttpURLConnection connection = null;
147             RandomAccessFile randomAccessFile = null;
148             InputStream is = null;
149             try {
150                 URL url = new URL(urlstr);
151                 connection = (HttpURLConnection) url.openConnection();
152                 connection.setConnectTimeout(5000);
153                 connection.setRequestMethod("GET");
154                 // 設置範圍,格式爲Range:bytes x-y;
155                 connection.setRequestProperty("Range", "bytes="+(startPos + compeleteSize) + "-" + endPos);
156
157                 randomAccessFile = new RandomAccessFile(localfile, "rwd");
158                 randomAccessFile.seek(startPos + compeleteSize);
159                 // 將要下載的文件寫到保存在保存路徑下的文件中
160                 is = connection.getInputStream();
161                 byte[] buffer = new byte[4096];
162                 int length = -1;
163                 while ((length = is.read(buffer)) != -1) {
164                     randomAccessFile.write(buffer, 0, length);
165                     compeleteSize += length;
166                     // 更新數據庫中的下載信息
167                     dao.updataInfos(threadId, compeleteSize, urlstr);
168                     // 用消息將下載信息傳給進度條,對進度條進行更新
169                     Message message = Message.obtain();
170                     message.what = 1;
171                     message.obj = urlstr;
172                     message.arg1 = length;
173                     mHandler.sendMessage(message);
174                     if (state == PAUSE) {
175                         return;
176                     }
177                 }
178             } catch (Exception e) {
179                 e.printStackTrace();
180             } finally {
181                 try {
182                     is.close();
183                     randomAccessFile.close();
184                     connection.disconnect();
185                     dao.closeDb();
186                 } catch (Exception e) {
187                     e.printStackTrace();
188                 }
189             }
190
191         }
192     }
193     //刪除數據庫中urlstr對應的下載器信息
194     public void delete(String urlstr) {
195         dao.delete(urlstr);
196     }
197     //設置暫停
198     public void pause() {
199         state = PAUSE;
200     }
201     //重置下載狀態
202     public void reset() {
203         state = INIT;
204     }
205 }

在這邊下載器類的定義中,咱們用到了許多關於進行數據庫操做的方法,這裏我定義了一個數據庫工具類,來提供這些方法,代碼以下:

Dao:

  1. 1 package cn.yj3g.Dao;  
  2.  2  
  3.  3 import java.util.ArrayList;  
  4.  4 import java.util.List;  
  5.  5 import android.content.Context;  
  6.  6 import android.database.Cursor;  
  7.  7 import android.database.sqlite.SQLiteDatabase;  
  8.  8 import cn.yj3g.DBHelper.DBHelper;  
  9.  9 import cn.yj3g.entity.DownloadInfo;  
  10. 10  
  11. 11 /** 
  12. 12  * 
  13. 13  * 一個業務類 
  14. 14  */  
  15. 15 public class Dao {  
  16. 16     private DBHelper dbHelper;  
  17. 17  
  18. 18     public Dao(Context context) {  
  19. 19         dbHelper = new DBHelper(context);  
  20. 20     }  
  21. 21  
  22. 22     /** 
  23. 23      * 查看數據庫中是否有數據 
  24. 24      */  
  25. 25     public boolean isHasInfors(String urlstr) {  
  26. 26         SQLiteDatabase database = dbHelper.getReadableDatabase();  
  27. 27         String sql = "select count(*)  from download_info where url=?";  
  28. 28         Cursor cursor = database.rawQuery(sql, new String[] { urlstr });  
  29. 29         cursor.moveToFirst();  
  30. 30         int count = cursor.getInt(0);  
  31. 31         cursor.close();  
  32. 32         return count == 0;  
  33. 33     }  
  34. 34  
  35. 35     /** 
  36. 36      * 保存 下載的具體信息 
  37. 37      */  
  38. 38     public void saveInfos(List<DownloadInfo> infos) {  
  39. 39         SQLiteDatabase database = dbHelper.getWritableDatabase();  
  40. 40         for (DownloadInfo info : infos) {  
  41. 41             String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";  
  42. 42             Object[] bindArgs = { info.getThreadId(), info.getStartPos(),  
  43. 43                     info.getEndPos(), info.getCompeleteSize(), info.getUrl() };  
  44. 44             database.execSQL(sql, bindArgs);  
  45. 45         }  
  46. 46     }  
  47. 47  
  48. 48     /** 
  49. 49      * 獲得下載具體信息 
  50. 50      */  
  51. 51     public List<DownloadInfo> getInfos(String urlstr) {  
  52. 52         List<DownloadInfo> list = new ArrayList<DownloadInfo>();  
  53. 53         SQLiteDatabase database = dbHelper.getReadableDatabase();  
  54. 54         String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";  
  55. 55         Cursor cursor = database.rawQuery(sql, new String[] { urlstr });  
  56. 56         while (cursor.moveToNext()) {  
  57. 57             DownloadInfo info = new DownloadInfo(cursor.getInt(0),  
  58. 58                     cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),  
  59. 59                     cursor.getString(4));  
  60. 60             list.add(info);  
  61. 61         }  
  62. 62         cursor.close();  
  63. 63         return list;  
  64. 64     }  
  65. 65  
  66. 66     /** 
  67. 67      * 更新數據庫中的下載信息 
  68. 68      */  
  69. 69     public void updataInfos(int threadId, int compeleteSize, String urlstr) {  
  70. 70         SQLiteDatabase database = dbHelper.getReadableDatabase();  
  71. 71         String sql = "update download_info set compelete_size=? where thread_id=? and url=?";  
  72. 72         Object[] bindArgs = { compeleteSize, threadId, urlstr };  
  73. 73         database.execSQL(sql, bindArgs);  
  74. 74     }  
  75. 75     /** 
  76. 76      * 關閉數據庫 
  77. 77      */  
  78. 78     public void closeDb() {  
  79. 79         dbHelper.close();  
  80. 80     }  
  81. 81  
  82. 82     /** 
  83. 83      * 下載完成後刪除數據庫中的數據 
  84. 84      */  
  85. 85     public void delete(String url) {  
  86. 86         SQLiteDatabase database = dbHelper.getReadableDatabase();  
  87. 87         database.delete("download_info""url=?"new String[] { url });  
  88. 88         database.close();  
  89. 89     }  
  90. 90 }  

1 package cn.yj3g.Dao;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import android.content.Context;
 6 import android.database.Cursor;
 7 import android.database.sqlite.SQLiteDatabase;
 8 import cn.yj3g.DBHelper.DBHelper;
 9 import cn.yj3g.entity.DownloadInfo;
10
11 /**
12  *
13  * 一個業務類
14  */
15 public class Dao {
16     private DBHelper dbHelper;
17
18     public Dao(Context context) {
19         dbHelper = new DBHelper(context);
20     }
21
22     /**
23      * 查看數據庫中是否有數據
24      */
25     public boolean isHasInfors(String urlstr) {
26         SQLiteDatabase database = dbHelper.getReadableDatabase();
27         String sql = "select count(*)  from download_info where url=?";
28         Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
29         cursor.moveToFirst();
30         int count = cursor.getInt(0);
31         cursor.close();
32         return count == 0;
33     }
34
35     /**
36      * 保存 下載的具體信息
37      */
38     public void saveInfos(List<DownloadInfo> infos) {
39         SQLiteDatabase database = dbHelper.getWritableDatabase();
40         for (DownloadInfo info : infos) {
41             String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";
42             Object[] bindArgs = { info.getThreadId(), info.getStartPos(),
43                     info.getEndPos(), info.getCompeleteSize(), info.getUrl() };
44             database.execSQL(sql, bindArgs);
45         }
46     }
47
48     /**
49      * 獲得下載具體信息
50      */
51     public List<DownloadInfo> getInfos(String urlstr) {
52         List<DownloadInfo> list = new ArrayList<DownloadInfo>();
53         SQLiteDatabase database = dbHelper.getReadableDatabase();
54         String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";
55         Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
56         while (cursor.moveToNext()) {
57             DownloadInfo info = new DownloadInfo(cursor.getInt(0),
58                     cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),
59                     cursor.getString(4));
60             list.add(info);
61         }
62         cursor.close();
63         return list;
64     }
65
66     /**
67      * 更新數據庫中的下載信息
68      */
69     public void updataInfos(int threadId, int compeleteSize, String urlstr) {
70         SQLiteDatabase database = dbHelper.getReadableDatabase();
71         String sql = "update download_info set compelete_size=? where thread_id=? and url=?";
72         Object[] bindArgs = { compeleteSize, threadId, urlstr };
73         database.execSQL(sql, bindArgs);
74     }
75     /**
76      * 關閉數據庫
77      */
78     public void closeDb() {
79         dbHelper.close();
80     }
81
82     /**
83      * 下載完成後刪除數據庫中的數據
84      */
85     public void delete(String url) {
86         SQLiteDatabase database = dbHelper.getReadableDatabase();
87         database.delete("download_info", "url=?", new String[] { url });
88         database.close();
89     }
90 }

下來就是要進行下載和暫停按鈕的響應事件了。具體代碼和解釋以下。

MainActivity:

  1.   1 package cn.yj3g.AndroidDownload;  
  2.   2  
  3.   3 import java.util.ArrayList;  
  4.   4 import java.util.HashMap;  
  5.   5 import java.util.List;  
  6.   6 import java.util.Map;  
  7.   7 import android.app.ListActivity;  
  8.   8 import android.os.Bundle;  
  9.   9 import android.os.Handler;  
  10.  10 import android.os.Message;  
  11.  11 import android.view.View;  
  12.  12 import android.widget.LinearLayout;  
  13.  13 import android.widget.LinearLayout.LayoutParams;  
  14.  14 import android.widget.ProgressBar;  
  15.  15 import android.widget.SimpleAdapter;  
  16.  16 import android.widget.TextView;  
  17.  17 import android.widget.Toast;  
  18.  18 import cn.yj3g.entity.LoadInfo;  
  19.  19 import cn.yj3g.service.Downloader;  
  20.  20  
  21.  21 public class MainActivity extends ListActivity {  
  22.  22     // 固定下載的資源路徑,這裏能夠設置網絡上的地址  
  23.  23     private static final String URL = "http://192.168.1.105:8080/struts2_net/";  
  24.  24     // 固定存放下載的音樂的路徑:SD卡目錄下  
  25.  25     private static final String SD_PATH = "/mnt/sdcard/";  
  26.  26     // 存放各個下載器  
  27.  27     private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();  
  28.  28     // 存放與下載器對應的進度條  
  29.  29     private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();  
  30.  30     /** 
  31.  31      * 利用消息處理機制適時更新進度條 
  32.  32      */  
  33.  33     private Handler mHandler = new Handler() {  
  34.  34         public void handleMessage(Message msg) {  
  35.  35             if (msg.what == 1) {  
  36.  36                 String url = (String) msg.obj;  
  37.  37                 int length = msg.arg1;  
  38.  38                 ProgressBar bar = ProgressBars.get(url);  
  39.  39                 if (bar != null) {  
  40.  40                     // 設置進度條按讀取的length長度更新  
  41.  41                     bar.incrementProgressBy(length);  
  42.  42                     if (bar.getProgress() == bar.getMax()) {  
  43.  43                         Toast.makeText(MainActivity.this"下載完成!"0).show();  
  44.  44                         // 下載完成後清除進度條並將map中的數據清空  
  45.  45                         LinearLayout layout = (LinearLayout) bar.getParent();  
  46.  46                         layout.removeView(bar);  
  47.  47                         ProgressBars.remove(url);  
  48.  48                         downloaders.get(url).delete(url);  
  49.  49                         downloaders.get(url).reset();  
  50.  50                         downloaders.remove(url);  
  51.  51  
  52.  52                     }  
  53.  53                 }  
  54.  54             }  
  55.  55         }  
  56.  56     };  
  57.  57     @Override  
  58.  58     public void onCreate(Bundle savedInstanceState) {  
  59.  59         super.onCreate(savedInstanceState);  
  60.  60         setContentView(R.layout.main);  
  61.  61         showListView();  
  62.  62     }  
  63.  63     // 顯示listView,這裏能夠隨便添加音樂  
  64.  64     private void showListView() {  
  65.  65         List<Map<String, String>> data = new ArrayList<Map<String, String>>();  
  66.  66         Map<String, String> map = new HashMap<String, String>();  
  67.  67         map.put("name""mm.mp3");  
  68.  68         data.add(map);  
  69.  69         map = new HashMap<String, String>();  
  70.  70         map.put("name""pp.mp3");  
  71.  71         data.add(map);  
  72.  72         map = new HashMap<String, String>();  
  73.  73         map.put("name""tt.mp3");  
  74.  74         data.add(map);  
  75.  75         map = new HashMap<String, String>();  
  76.  76         map.put("name""You.mp3");  
  77.  77         data.add(map);  
  78.  78         SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_item, new String[] { "name" },  
  79.  79                 new int[] { R.id.tv_resouce_name });  
  80.  80         setListAdapter(adapter);  
  81.  81     }  
  82.  82     /** 
  83.  83      * 響應開始下載按鈕的點擊事件 
  84.  84      */  
  85.  85     public void startDownload(View v) {  
  86.  86         // 獲得textView的內容  
  87.  87         LinearLayout layout = (LinearLayout) v.getParent();  
  88.  88         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();  
  89.  89         String urlstr = URL + musicName;  
  90.  90         String localfile = SD_PATH + musicName;  
  91.  91         //設置下載線程數爲4,這裏是我爲了方便隨便固定的  
  92.  92         int threadcount = 4;  
  93.  93         // 初始化一個downloader下載器  
  94.  94         Downloader downloader = downloaders.get(urlstr);  
  95.  95         if (downloader == null) {  
  96.  96             downloader = new Downloader(urlstr, localfile, threadcount, this, mHandler);  
  97.  97             downloaders.put(urlstr, downloader);  
  98.  98         }  
  99.  99         if (downloader.isdownloading())  
  100. 100             return;  
  101. 101         // 獲得下載信息類的個數組成集合  
  102. 102         LoadInfo loadInfo = downloader.getDownloaderInfors();  
  103. 103         // 顯示進度條  
  104. 104         showProgress(loadInfo, urlstr, v);  
  105. 105         // 調用方法開始下載  
  106. 106         downloader.download();  
  107. 107     }  
  108. 108  
  109. 109     /** 
  110. 110      * 顯示進度條 
  111. 111      */  
  112. 112     private void showProgress(LoadInfo loadInfo, String url, View v) {  
  113. 113         ProgressBar bar = ProgressBars.get(url);  
  114. 114         if (bar == null) {  
  115. 115             bar = new ProgressBar(thisnull, android.R.attr.progressBarStyleHorizontal);  
  116. 116             bar.setMax(loadInfo.getFileSize());  
  117. 117             bar.setProgress(loadInfo.getComplete());  
  118. 118             ProgressBars.put(url, bar);  
  119. 119             LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);  
  120. 120             ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);  
  121. 121         }  
  122. 122     }  
  123. 123     /** 
  124. 124      * 響應暫停下載按鈕的點擊事件 
  125. 125      */  
  126. 126     public void pauseDownload(View v) {  
  127. 127         LinearLayout layout = (LinearLayout) v.getParent();  
  128. 128         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();  
  129. 129         String urlstr = URL + musicName;  
  130. 130         downloaders.get(urlstr).pause();  
  131. 131     }  
  132. 132 }  

1 package cn.yj3g.AndroidDownload;
  2
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 import android.app.ListActivity;
  8 import android.os.Bundle;
  9 import android.os.Handler;
 10 import android.os.Message;
 11 import android.view.View;
 12 import android.widget.LinearLayout;
 13 import android.widget.LinearLayout.LayoutParams;
 14 import android.widget.ProgressBar;
 15 import android.widget.SimpleAdapter;
 16 import android.widget.TextView;
 17 import android.widget.Toast;
 18 import cn.yj3g.entity.LoadInfo;
 19 import cn.yj3g.service.Downloader;
 20
 21 public class MainActivity extends ListActivity {
 22     // 固定下載的資源路徑,這裏能夠設置網絡上的地址
 23     private static final String URL = "http://192.168.1.105:8080/struts2_net/";
 24     // 固定存放下載的音樂的路徑:SD卡目錄下
 25     private static final String SD_PATH = "/mnt/sdcard/";
 26     // 存放各個下載器
 27     private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();
 28     // 存放與下載器對應的進度條
 29     private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();
 30     /**
 31      * 利用消息處理機制適時更新進度條
 32      */
 33     private Handler mHandler = new Handler() {
 34         public void handleMessage(Message msg) {
 35             if (msg.what == 1) {
 36                 String url = (String) msg.obj;
 37                 int length = msg.arg1;
 38                 ProgressBar bar = ProgressBars.get(url);
 39                 if (bar != null) {
 40                     // 設置進度條按讀取的length長度更新
 41                     bar.incrementProgressBy(length);
 42                     if (bar.getProgress() == bar.getMax()) {
 43                         Toast.makeText(MainActivity.this, "下載完成!", 0).show();
 44                         // 下載完成後清除進度條並將map中的數據清空
 45                         LinearLayout layout = (LinearLayout) bar.getParent();
 46                         layout.removeView(bar);
 47                         ProgressBars.remove(url);
 48                         downloaders.get(url).delete(url);
 49                         downloaders.get(url).reset();
 50                         downloaders.remove(url);
 51
 52                     }
 53                 }
 54             }
 55         }
 56     };
 57     @Override
 58     public void onCreate(Bundle savedInstanceState) {
 59         super.onCreate(savedInstanceState);
 60         setContentView(R.layout.main);
 61         showListView();
 62     }
 63     // 顯示listView,這裏能夠隨便添加音樂
 64     private void showListView() {
 65         List<Map<String, String>> data = new ArrayList<Map<String, String>>();
 66         Map<String, String> map = new HashMap<String, String>();
 67         map.put("name", "mm.mp3");
 68         data.add(map);
 69         map = new HashMap<String, String>();
 70         map.put("name", "pp.mp3");
 71         data.add(map);
 72         map = new HashMap<String, String>();
 73         map.put("name", "tt.mp3");
 74         data.add(map);
 75         map = new HashMap<String, String>();
 76         map.put("name", "You.mp3");
 77         data.add(map);
 78         SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_item, new String[] { "name" },
 79                 new int[] { R.id.tv_resouce_name });
 80         setListAdapter(adapter);
 81     }
 82     /**
 83      * 響應開始下載按鈕的點擊事件
 84      */
 85     public void startDownload(View v) {
 86         // 獲得textView的內容
 87         LinearLayout layout = (LinearLayout) v.getParent();
 88         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
 89         String urlstr = URL + musicName;
 90         String localfile = SD_PATH + musicName;
 91         //設置下載線程數爲4,這裏是我爲了方便隨便固定的
 92         int threadcount = 4;
 93         // 初始化一個downloader下載器
 94         Downloader downloader = downloaders.get(urlstr);
 95         if (downloader == null) {
 96             downloader = new Downloader(urlstr, localfile, threadcount, this, mHandler);
 97             downloaders.put(urlstr, downloader);
 98         }
 99         if (downloader.isdownloading())
100             return;
101         // 獲得下載信息類的個數組成集合
102         LoadInfo loadInfo = downloader.getDownloaderInfors();
103         // 顯示進度條
104         showProgress(loadInfo, urlstr, v);
105         // 調用方法開始下載
106         downloader.download();
107     }
108
109     /**
110      * 顯示進度條
111      */
112     private void showProgress(LoadInfo loadInfo, String url, View v) {
113         ProgressBar bar = ProgressBars.get(url);
114         if (bar == null) {
115             bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
116             bar.setMax(loadInfo.getFileSize());
117             bar.setProgress(loadInfo.getComplete());
118             ProgressBars.put(url, bar);
119             LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);
120             ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);
121         }
122     }
123     /**
124      * 響應暫停下載按鈕的點擊事件
125      */
126     public void pauseDownload(View v) {
127         LinearLayout layout = (LinearLayout) v.getParent();
128         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
129         String urlstr = URL + musicName;
130         downloaders.get(urlstr).pause();
131     }
132 }

最後咱們要在清單文件中添加權限,一個是訪問網絡的權限,一個是往SD卡寫數據的權限。代碼以下:
  1. <uses-permission android:name="android.permission.INTERNET"/>  
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

這樣咱們就實現了文件的斷點續傳下載功能。具體效果圖以下:

相關文章
相關標籤/搜索