Android实现多线程断点下载的方法

时间:2021-05-02

本文实例讲述了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程序设计有所帮助。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章