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     <EditText
13         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     <ProgressBar
20         android:id="@+id/pb"
21         style="?android:attr/progressBarStyleHorizontal"
22         android:layout_width="fill_parent"
23         android:layout_height="wrap_content" />
24 
25     <TextView
26         android:id="@+id/tv_process"
27         android:layout_width="fill_parent"
28         android:layout_height="wrap_content" />
29 
30     <Button
31         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 线程3
105                      * 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         @Override
148         public void run() {
149             try {
150               File postionfile = new File("/mnt/sdcard/" + threadid + ".txt");
151                 URL url = new URL(filepath);
152                 HttpURLConnection conn = (HttpURLConnection) url
153                         .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"/>

原文地址:https://www.cnblogs.com/androidsj/p/3966258.html