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