首页 > 代码库 > 33、多线程断点下载的实现&界面的更新

33、多线程断点下载的实现&界面的更新

 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3     android:layout_width="fill_parent" 4     android:layout_height="fill_parent" 5     android:orientation="vertical" > 6  7     <TextView 8         android:layout_width="fill_parent" 9         android:layout_height="wrap_content"10         android:text="@string/down_load" />11 12     <EditText13         android:id="@+id/et"14         android:layout_width="fill_parent"15         android:layout_height="wrap_content"16         android:hint="@string/hint"17         android:text="http://192.168.1.247:8080/youdao.exe" />18 19     <ProgressBar20         android:id="@+id/pb"21         style="?android:attr/progressBarStyleHorizontal"22         android:layout_width="fill_parent"23         android:layout_height="wrap_content" />24 25     <TextView26         android:id="@+id/tv_process"27         android:layout_width="fill_parent"28         android:layout_height="wrap_content" />29 30     <Button31         android:id="@+id/bt"32         android:layout_width="fill_parent"33         android:layout_height="wrap_content"34         android:text="@string/download" />35 36 </LinearLayout>

 

  1 /**  2  * 49_多线程断点下载的实现&界面的更新 DEMO  3  * @author dr  4  *  5  */  6 public class DemoActivity extends Activity implements OnClickListener {  7   8     private ProgressBar pb;  9     private Button bt; 10     private TextView tv; 11     private EditText et; 12     boolean flag = true; 13     boolean stopflag = false; 14     int total = 0; 15  16     private Handler handler = new Handler() { 17  18         @Override 19         public void handleMessage(Message msg) { 20             pb.setProgress(total); 21             // 文件总长度 22             int max = pb.getMax();   23             // total和max都是从0开始的。 24             if (total >= (max - 1)) {  25                 total = max; 26                 flag = false; 27             } 28             int result = total * 100 / max; 29             tv.setText("当前进度 :" + result + "%"); 30  31             super.handleMessage(msg); 32         } 33     }; 34  35     @Override 36     public void onCreate(Bundle savedInstanceState) { 37         super.onCreate(savedInstanceState); 38         setContentView(R.layout.main); 39         pb = (ProgressBar) this.findViewById(R.id.pb); 40         bt = (Button) this.findViewById(R.id.bt); 41         tv = (TextView) this.findViewById(R.id.tv_process); 42         et = (EditText) this.findViewById(R.id.et); 43         bt.setOnClickListener(this); 44  45     } 46  47     @Override 48     public void onClick(View v) { 49         switch (v.getId()) { 50         case R.id.bt: 51             // 创建一个子线程 定期的更新ui 52             if ("开始下载".equals(bt.getText().toString())) { 53                 bt.setText("暂停"); 54                 stopflag = false; // 开始下载 55             } else { 56                 bt.setText("开始下载"); 57                 stopflag = true; 58             } 59             new Thread() { 60                 @Override 61                 public void run() { 62                     super.run(); 63                     while (flag) { 64                         try { 65                             sleep(1000); 66                             // 如果total > = 文件长度 67                             Message msg = new Message(); 68                             handler.sendMessage(msg); 69                         } catch (InterruptedException e) { 70                             e.printStackTrace(); 71                         } 72                     } 73                 } 74             }.start(); 75  76             // 开始执行下载的操作 77             String path = et.getText().toString().trim(); 78             if ("".equals(path)) { 79                 Toast.makeText(this, "路径不能为空", 1).show(); 80                 return; 81             } 82             try { 83                 URL url = new URL(path); 84                 HttpURLConnection conn = (HttpURLConnection) url 85                         .openConnection(); 86                 conn.setRequestMethod("GET"); 87                 conn.setConnectTimeout(5000); 88                 conn.setRequestProperty("User-Agent", 89                         "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); 90                 int code = conn.getResponseCode(); 91                 if (code == 200) { 92                     int len = conn.getContentLength(); 93                     RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/" 94                             + getFilenName(path), "rwd"); 95                     // 1.设置本地文件大小跟服务器的文件大小一致 96                     file.setLength(len); 97                     // 设置进度条的最大值 98                     pb.setMax(len); 99 100                     // 2 .假设开启3 个线程101                     int threadnumber = 3;102                     int blocksize = len / threadnumber;103                     /**104                      * 线程1 0~ blocksize 线程2 1*bolocksize ~ 2*blocksize 线程3105                      * 2*blocksize ~ 文件末尾106                      */107                     for (int i = 0; i < threadnumber; i++) {108                         int startposition = i * blocksize;109                         int endpositon = (i + 1) * blocksize;110                         if (i == (threadnumber - 1)) {111                             // 最后一个线程112                             endpositon = len;113                         }114 115                         DownLoadTask task = new DownLoadTask(i, path,116                                 startposition, endpositon);117                         task.start();118                     }119 120                 }121             } catch (Exception e) {122                 Toast.makeText(this, "下载出现异常", 0).show();123                 e.printStackTrace();124             }125 126             break;127         }128 129     }130 131     class DownLoadTask extends Thread {132 133         int threadid;134         String filepath;135         int startposition;136         int endpositon;137 138         public DownLoadTask(int threadid, String filepath, int startposition,139                 int endpositon) {140             this.threadid = threadid;141             this.filepath = filepath;142             this.startposition = startposition;143             this.endpositon = endpositon;144 145         }146 147         @Override148         public void run() {149             try {150               File postionfile = new File("/mnt/sdcard/" + threadid + ".txt");151                 URL url = new URL(filepath);152                 HttpURLConnection conn = (HttpURLConnection) url153                         .openConnection();154                 System.out.println("线程" + threadid + "正在下载 " + "开始位置 : "155                         + startposition + "结束位置 " + endpositon);156 157                 if (postionfile.exists()) {158                     FileInputStream fis = new FileInputStream(postionfile);159                     byte[] result = StreamTool.getBytes(fis);160                     String str = new String(result);161                     if (!"".equals(str)) {162                         int newstartposition = Integer.parseInt(str);163                         if (newstartposition > startposition) {164                             startposition = newstartposition;165                         }166                     }167                 }168 169                 // "Range", "bytes=2097152-4194303")170                 conn.setRequestProperty("Range", "bytes=" + startposition + "-"171                         + endpositon);172                 conn.setRequestMethod("GET");173                 conn.setConnectTimeout(5000);174                 conn.setRequestProperty("User-Agent",175                         "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");176                 InputStream is = conn.getInputStream();177                 RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/"178                         + getFilenName(filepath), "rwd");179                 // 设置 数据从文件哪个位置开始写180                 file.seek(startposition);181                 byte[] buffer = new byte[1024];182                 int len = 0;183                 // 代表当前读到的服务器数据的位置 ,同时这个值已经存储的文件的位置184                 int currentPostion = startposition;185                 // 创建一个文件对象 ,记录当前某个文件的下载位置186 187                 while ((len = is.read(buffer)) != -1) {188                     if (stopflag) {   // 暂停下载189                         return;190                     }191                     file.write(buffer, 0, len);192 193                     synchronized (DemoActivity.this) { // 同步当前的194                         total += len;195                     }196 197                     currentPostion += len;198                     // 需要把currentPostion 信息给持久化到存储设备199                     String position = currentPostion + "";200                     FileOutputStream fos = new FileOutputStream(postionfile);201                     fos.write(position.getBytes());202                     fos.flush();203                     fos.close();204                 }205 206                 file.close();207                 System.out.println("线程" + threadid + "下载完毕");208                 // 当线程下载完毕后 把文件删除掉209                 if (postionfile.exists()) {210                     postionfile.delete();211                 }212             } catch (Exception e) {213                 e.printStackTrace();214             }215             super.run();216         }217     }218 219     public String getFilenName(String path) {220         int start = path.lastIndexOf("/") + 1;221         return path.substring(start, path.length());222     }223 }

 

 1 public class StreamTool { 2     /** 3      * 把一个inputstream里面的内容转化成一个byte[]  4      */ 5     public static byte[] getBytes(InputStream is) throws Exception{ 6         ByteArrayOutputStream bos = new ByteArrayOutputStream(); 7         byte[] buffer = new byte[1024]; 8         int len = 0; 9         while((len = is.read(buffer))!=-1){10             bos.write(buffer, 0, len);11         }12         is.close();13         bos.flush();14         byte[] result = bos.toByteArray();15         System.out.println(new String(result));16         return  result;17     }18 }

 

1     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>2     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>3     <uses-permission android:name="android.permission.INTERNET"/>

 

33、多线程断点下载的实现&界面的更新