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

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

效果:

打开软件:

Ic1tcNii6FpxpTLW.png

下载中:

sgqJuWdzV4lWOLgN.png

下载完毕:

peFgx7esGPc0hCTz.png

附代码如下:

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 }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值