android多線程斷點下載-帶進度條和百分比進度顯示


歡迎訪問個人博客:www.yyxxk.com

android多線程斷點下載,帶進度條和百分比顯示,斷點下載的臨時數據保存到SD卡的文本文檔中,建議可以保存到本地數據庫中,這樣可以提高存取效率,從而提高系統性能。

效果:

打開軟件:

下載中:

下載完畢:

附代碼如下:

  1 package com.yy.multiDownloadOfBreakPoint;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.InputStream;
  6 import java.io.RandomAccessFile;
  7 import java.net.HttpURLConnection;
  8 import java.net.URL;
  9 
 10 import android.app.Activity;
 11 import android.os.Bundle;
 12 import android.os.Handler;
 13 import android.os.Message;
 14 import android.text.TextUtils;
 15 import android.view.View;
 16 import android.widget.EditText;
 17 import android.widget.ProgressBar;
 18 import android.widget.TextView;
 19 import android.widget.Toast;
 20 /**
 21  * 多線程斷點下載實例
 22  * @author YUANYUAN
 23  *
 24  */
 25 public class MainActivity extends Activity {
 26     //下載所使用的線程數
 27     protected static final int threadCount = 3;
 28     //下載完畢的標記
 29     public static final int downloadOver = 1;
 30     //更新下載進度標記
 31     public static final int UPDATE_PROGRESS = 0;
 32     //下載資源的路徑輸入框
 33     private EditText et_path;
 34     //下載的進度條
 35     private ProgressBar pb;
 36     //進度顯示
 37     private TextView tv_pb;
 38     //當前累計下載的數據
 39     int curDownCount=0;
 40     //當前活動的下載線程數
 41     protected static int activeThread;
 42     //加入消息處理機制
 43     private Handler handler=new Handler(){
 44         @Override
 45         public void handleMessage(Message msg) {
 46             switch (msg.what) {
 47             case downloadOver:
 48                 Toast.makeText(MainActivity.this, "文件已下載完畢!", Toast.LENGTH_LONG).show();
 49                 tv_pb.setText("下載完成");
 50                 break;
 51             case UPDATE_PROGRESS:
 52                 //更新進度顯示
 53                 tv_pb.setText("當前進度:"+(pb.getProgress()*100/pb.getMax())+"%");
 54                 break;
 55             default:
 56                 break;
 57             }
 58         }
 59     };
 60 
 61     @Override
 62     protected void onCreate(Bundle savedInstanceState) {
 63         super.onCreate(savedInstanceState);
 64         setContentView(R.layout.activity_main);
 65         et_path=(EditText) findViewById(R.id.et_path);
 66         et_path.setText("http://192.168.2.114:8080/sqlite.exe");
 67         pb=(ProgressBar) findViewById(R.id.pb);
 68         tv_pb=(TextView) findViewById(R.id.tv_pb);
 69     }
 70     
 71     /**
 72      * 開始下載
 73      * @param view
 74      */
 75     public void down(View view){
 76         //獲取下載資源的路徑
 77         final String path=et_path.getText().toString().trim();
 78         //判斷資源路徑是否為空
 79         if (TextUtils.isEmpty(path)) {
 80             Toast.makeText(this, "請輸入下載資源的路徑", Toast.LENGTH_LONG).show();
 81             return;
 82         }
 83         //開啟一個線程進行下載
 84         new Thread(){
 85             public void run() {
 86                 try {
 87                     //構造URL地址
 88                     URL url=new URL(path);
 89                     //打開連接
 90                     HttpURLConnection conn=(HttpURLConnection) url.openConnection();
 91                     //設置請求超時的時間
 92                     conn.setConnectTimeout(5000);
 93                     //設置請求方式
 94                     conn.setRequestMethod("GET");
 95                     //獲取相應碼
 96                     int code=conn.getResponseCode();
 97                     if (code==200) {//請求成功
 98                         //獲取請求數據的長度
 99                         int length=conn.getContentLength();
100                         //設置進度條的最大值
101                         pb.setMax(length);
102                         //在客戶端創建一個跟服務器文件大小相同的臨時文件
103                         RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");
104                         //指定臨時文件的長度
105                         raf.setLength(length);
106                         raf.close();
107                         //假設3個線程去下載資源
108                         //平均每一個線程要下載的文件的大小
109                         int blockSize=length/threadCount;
110                         for (int threadId = 1; threadId <= threadCount; threadId++) {
111                             //當前線程下載數據的開始位置
112                             int startIndex=blockSize*(threadId-1);
113                             //當前線程下載數據的結束位置
114                             int endIndex=blockSize*threadId-1;
115                             //確定最后一個線程要下載數據的最大位置
116                             if (threadId==threadCount) {
117                                 endIndex=length;
118                             }
119                             //顯示下載數據的區間
120                             System.out.println("線程【"+threadId+"】開始下載:"+startIndex+"---->"+endIndex);
121                             //開啟下載的子線程
122                             new DownloadThread(path, threadId, startIndex, endIndex).start();
123                             //當前下載活動的線程數加1
124                             activeThread++;
125                             System.out.println("當前活動的線程數:"+activeThread);
126                         }
127                         
128                     }else{//請求失敗
129                         System.out.println("服務器異常,下載失敗!");
130                     }
131                 } catch (Exception e) {
132                     e.printStackTrace();
133                     System.out.println("服務器異常,下載失敗!");
134                 }
135             };
136         }.start();
137         
138     }
139     /**
140      * 下載文件的子線程 每一個文件都下載對應的數據
141      * @author YUANYUAN
142      *
143      */
144     public class DownloadThread extends Thread{
145         private String path;
146         private int threadId;
147         private int startIndex;
148         private int endIndex;
149         
150         /**
151          * 構造方法
152          * @param path 下載文件的路徑
153          * @param threadId 下載文件的線程
154          * @param startIndex 下載文件開始的位置
155          * @param endIndex 下載文件結束的位置
156          */
157         public DownloadThread(String path, int threadId, int startIndex,
158                 int endIndex) {
159             this.path = path;
160             this.threadId = threadId;
161             this.startIndex = startIndex;
162             this.endIndex = endIndex;
163         }
164 
165 
166 
167         @Override
168         public void run() {
169             //構造URL地址
170             try {
171                 
172                 File tempFile=new File("sdcard/"+threadId+".txt");
173                 //檢查記錄是否存在,如果存在讀取數據,設置真實下載開始的位置
174                 if (tempFile.exists()) {
175                     FileInputStream fis=new FileInputStream(tempFile);
176                     byte[] temp=new byte[1024];
177                     int length=fis.read(temp);
178                     //讀取到已經下載的位置
179                     int downloadNewIndex=Integer.parseInt(new String(temp, 0, length));
180                     //計算出已經下載的數據長度
181                     int areadyDown=downloadNewIndex-startIndex;
182                     //累加已經下載的數據量
183                     curDownCount+=areadyDown;
184                     //設置進度條已經下載的數據量
185                     pb.setProgress(curDownCount);
186                     //設置重新開始下載的開始位置
187                     startIndex=downloadNewIndex;
188                     fis.close();
189                     //顯示真實下載數據的區間
190                     System.out.println("線程【"+threadId+"】真實開始下載數據區間:"+startIndex+"---->"+endIndex);
191                 }
192                 
193                 URL url = new URL(path);
194                 HttpURLConnection conn=(HttpURLConnection) url.openConnection();
195                 conn.setConnectTimeout(5000);
196                 conn.setRequestMethod("GET");
197                 //設置請求屬性,請求部分資源
198                 conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
199                 int code=conn.getResponseCode();
200                 if (code==206) {//下載部分資源,正常返回的狀態碼為206
201                     InputStream is=conn.getInputStream();//已經設置了請求的位置,所以返回的是對應的部分資源
202                     //構建隨機訪問文件
203                     RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");
204                     //設置 每一個線程隨機寫文件開始的位置
205                     raf.seek(startIndex);
206                     //開始寫文件
207                     int len=0;
208                     byte[] buffer=new byte[1024];
209                     //該線程已經下載數據的長度
210                     int total=0;
211                     
212                     while((len=is.read(buffer))!=-1){//讀取輸入流
213                         //記錄當前線程已下載數據的長度
214                         RandomAccessFile file=new RandomAccessFile("sdcard/"+threadId+".txt","rwd");
215                         raf.write(buffer,0,len);//寫文件
216                         total+=len;//更新該線程已下載數據的總長度
217                         System.out.println("線程【"+threadId+"】已下載數據:"+(total+startIndex));
218                         //將已下載數據的位置記錄寫入到文件
219                         file.write((startIndex+total+"").getBytes());
220                         //累加已經下載的數據量
221                         curDownCount+=len;
222                         //更新進度條【進度條的更新可以在非UI線程直接更新,具體見底層源代碼】
223                         pb.setProgress(curDownCount);
224                         
225                         //更新下載進度
226                         Message msg=Message.obtain();
227                         msg.what=UPDATE_PROGRESS;
228                         handler.sendMessage(msg);
229                         
230                         file.close();
231                     }
232                     is.close();
233                     raf.close();
234                     //提示下載完畢
235                     System.out.println("線程【"+threadId+"】下載完畢");
236                 }
237             } catch (Exception e) {
238                 e.printStackTrace();
239                 System.out.println("線程【"+threadId+"】下載出現異常!!");
240             }finally{
241                 //活動的線程數減少
242                 activeThread--;
243                 if (activeThread==0) {
244                     for (int i = 1; i <= threadCount; i++) {
245                         File tempFile=new File("sdcard/"+i+".txt");
246                         tempFile.delete();
247                     }
248                     System.out.println("下載完畢,已清除全部臨時文件");
249                     //界面消息提示下載完畢
250                     Message msg=new Message();
251                     msg.what=downloadOver;
252                     handler.sendMessage(msg);
253                 }
254             }
255             
256         }
257     }
258 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM