转载

android多线程断点下载-带进度条和百分比进度显示

android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到SD卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能。

效果:

打开软件:

android多线程断点下载-带进度条和百分比进度显示

下载中:

android多线程断点下载-带进度条和百分比进度显示

下载完毕:

android多线程断点下载-带进度条和百分比进度显示

附代码如下:

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 }
正文到此结束
Loading...