Android 多线程断点下载
package com.itheima.mutiledownloader; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.renderscript.Program.TextureType; import android.text.TextUtils; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.Toast; public class MainActivity extends Activity { protected static final int DOWNLOAD_ERROR = 1; private static final int THREAD_DOWNLOAD_ERROR = 2; public static final int DONWLOAD_FINISH = 3; private EditText et_path; private EditText et_number; private LinearLayout ll_pb; private String path; private static int threadCount = 4; private static int blockSize = 0; private static int livingThread = 0; private List<ProgressBar> pbs; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case DOWNLOAD_ERROR: Toast.makeText(getApplicationContext(), "初始化下载失败", 1).show(); break; case THREAD_DOWNLOAD_ERROR: String str = (String) msg.obj; Toast.makeText(getApplicationContext(), str, 1).show(); break; case DONWLOAD_FINISH: Toast.makeText(getApplicationContext(), "下载完毕", 1).show(); findViewById(R.id.bt).setEnabled(true); break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_path = (EditText) findViewById(R.id.et_path); et_number = (EditText) findViewById(R.id.et_number); ll_pb = (LinearLayout) findViewById(R.id.ll_pb); } public void click(View view) { path = et_path.getText().toString().trim(); String strNumber = et_number.getText().toString().trim(); if (TextUtils.isEmpty(path) || TextUtils.isEmpty(strNumber)) { Toast.makeText(this, "请输入参数", 0).show(); return; } else { // 下载的线程的个数 threadCount = Integer.parseInt(strNumber); pbs = new ArrayList<ProgressBar>(); ll_pb.removeAllViews(); for (int i = 0; i < threadCount; i++) { ProgressBar pb = (ProgressBar) View.inflate( getApplicationContext(), R.layout.pb_item, null); pb.setPadding(5, 5, 5, 5); ll_pb.addView(pb, LayoutParams.MATCH_PARENT, 12); //在集合里面添加进度条的引用. pbs.add(pb); } findViewById(R.id.bt).setEnabled(false); new Thread() { public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); // 服务器文件的长度 int length = conn.getContentLength(); // 本地创建一个大小跟服务器一样的文件 RandomAccessFile raf = new RandomAccessFile(Environment .getExternalStorageDirectory() .getAbsolutePath() + "/" + getFileName(path), "rw"); raf.setLength(length); System.out.println("文件的总长度:" + length); // 计算每个线程下载的位置. blockSize = length / threadCount; System.out.println("每一个块的平均长度:" + blockSize); livingThread = threadCount; for (int i = 1; i <= threadCount; i++) { int startIndex = (i - 1) * blockSize; int endIndex = i * blockSize - 1; if (i == threadCount) { endIndex = length; } //设置进度条的总进度 pbs.get(i-1).setMax(endIndex-startIndex); new Thread( new DownLoadTask(i, startIndex, endIndex)) .start(); } } catch (Exception e) { e.printStackTrace(); Message msg = Message.obtain(); msg.what = DOWNLOAD_ERROR; handler.sendMessage(msg); } }; }.start(); } } /** * 获取下载的文件的名称 * * @param path * @return */ private static String getFileName(String path) { int start = path.lastIndexOf("/") + 1; return path.substring(start); } private class DownLoadTask implements Runnable { private int id; private int startIndex; private int endIndex; public DownLoadTask(int id, int startIndex, int endIndex) { this.id = id; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { try { int downloadCount = 0 ; URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); // 在每次下载之前,检查是否存在已经下载大小的记录文件. File f = new File(Environment.getExternalStorageDirectory() .getAbsolutePath() + "/" + getFileName(path) + id + ".txt"); if (f.exists() && f.length() > 0) { FileInputStream fis = new FileInputStream(f); BufferedReader br = new BufferedReader( new InputStreamReader(fis)); // 已经下载的大小. downloadCount = Integer.parseInt(br.readLine()); startIndex += downloadCount; br.close(); fis.close(); } conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); System.out.println("线程id:" + id + " 下载的位置:" + startIndex + "~~~" + endIndex); RandomAccessFile raf = new RandomAccessFile(Environment .getExternalStorageDirectory().getAbsolutePath() + "/" + getFileName(path), "rwd"); InputStream is = conn.getInputStream(); // 指定线程下载存放文件的开始位置. raf.seek(startIndex); int len = 0; byte[] buffer = new byte[4096]; int total = 0;// 记录当前线程下载的大小. while ((len = is.read(buffer)) != -1) { File file = new File(Environment .getExternalStorageDirectory().getAbsolutePath() + "/" + getFileName(path) + id + ".txt"); RandomAccessFile positionRaf = new RandomAccessFile(file, "rwd"); raf.write(buffer, 0, len); total += len; positionRaf.write(String.valueOf(total).getBytes()); positionRaf.close(); pbs.get(id-1).setProgress(total+downloadCount); } raf.close(); is.close(); System.out.println("线程:" + id + "下载完毕..."); } catch (Exception e) { e.printStackTrace(); Message msg = Message.obtain(); msg.what = THREAD_DOWNLOAD_ERROR; msg.obj = "线程:" + id + "下载失败."; handler.sendMessage(msg); } finally { synchronized (MainActivity.this) { livingThread--; if (livingThread <= 0) { System.out.println("全部下载完毕..."); Message msg = Message.obtain(); msg.what = DONWLOAD_FINISH; handler.sendMessage(msg); for (int i = 1; i <= threadCount; i++) { File f = new File(Environment .getExternalStorageDirectory() .getAbsolutePath() + "/" + getFileName(path) + i + ".txt"); System.out.println(f.delete()); } } } } } } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。