android 多线程下载与断点续传

多线程下载:

下载速度更快,服务器对每个线程平分资源,故线程越多,得到的资源越多,下载速度越快。


断点续传:

下载中断,再次下载时从上一次下载结束的位置开始下载,防止重复下载

下载结束后


代码:

package com.itheime.phonemultidown;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;

public class MainActivity extends Activity {

	static int threadCount = 3;			//下载线程数
	static int finishedThread = 0;		//完成的下载线程数
	String fileName = "baidu.html";		//要下载的文件名
	//确定下载地址,我们用Tomcat做服务器
	String path = "http://192.168.61.254:8080/" + fileName;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	//下载按钮点击时,调用此函数
	public void click(View v) {
		Thread t = new Thread(){		//开一个子线程
			@Override
			public void run() {
				try {					//发送GET请求,请求这个地址的资源
					URL url = new URL(path);
					HttpURLConnection conn = (HttpURLConnection) url.openConnection();
					conn.setRequestMethod("GET");
					conn.setReadTimeout(5000);
					conn.setConnectTimeout(5000);
					
					if (conn.getResponseCode() == 200) {
						int length = conn.getContentLength();	//得到请求资源文件的长度
						File file = new File(Environment.getExternalStorageDirectory(), fileName);
						//生成临时文件
						RandomAccessFile raf = new RandomAccessFile(file, "rwd");
						raf.setLength(length);					//设置临时文件的大小
						raf.close();
						int size = length / threadCount;		//计算每个线程应该下载多少字节
						for (int i = 0; i < threadCount; i++) {
							int startIndex = i * size;			//计算线程下载的开始和结束位置
							int endIndex = (i + 1) * size - 1;
							if (i == threadCount - 1) {			//最后一个线程,下到文件结束
								endIndex = length - 1;
							}
							new DownLoadThread(startIndex, endIndex, i).start();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		t.start();
	}
	
	class DownLoadThread extends Thread {		//下载线程内部类
		int startIndex;
		int endIndex;
		int threadId;
		
		public DownLoadThread(int startIndex, int endIndex, int threadId) {
			super();
			this.startIndex = startIndex;
			this.endIndex = endIndex;
			this.threadId = threadId;
		}
	
		@Override
		public void run() {
			try {
				//生成一个专门记录下载进度的临时文件
				File progressFile = new File(Environment.getExternalStorageDirectory(), 
					threadId + ".txt");
				//判断进度临时文件是否存在
				if (progressFile.exists()) {
					FileInputStream fis = new FileInputStream(progressFile);
					BufferedReader br = new BufferedReader(new InputStreamReader(fis));
					//从进度临时文件中取出上一次的下载总进度,与原本的开始位置相加,得到新的开始位置
					startIndex += Integer.parseInt(br.readLine());
					fis.close();
				}
				URL url = new URL(path);
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				conn.setReadTimeout(5000);
				conn.setConnectTimeout(5000);
				//设置本次http请求所请求数据的区间
				conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
				//请求部分数据,成功的响应码为206
				if (conn.getResponseCode() == 206) {
					//流里此时只有1/3原文件的数据
					InputStream is = conn.getInputStream();
					byte[] b = new byte[1024];
					int len = 0;
					File file = new File(Environment.getExternalStorageDirectory(), fileName);
					//拿到临时文件的输出流
					RandomAccessFile raf = new RandomAccessFile(file, "rwd");
					//把文件的写入位置移动至startIndex
					raf.seek(startIndex);
					int total = 0;
					while ((len = is.read(b)) != -1) {
						raf.write(b, 0, len);		//每次读取流里的数据后,把数据写入临时文件
						total += len;
//						System.out.println("线程" + threadId + "下载了" + total);
						RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
						//每次读取流里的数据后,把当前线程下载的总进度写入进度临时文件中
						progressRaf.write((total + "").getBytes());
						progressRaf.close();
					}
//					System.out.println("线程" + threadId + "下载完毕----------------");
					raf.close();
					
					finishedThread++;
					synchronized(path) {
						if (finishedThread == threadCount) {		//所有线程下载完毕后将进度临时文件删除
							for (int i = 0; i < threadCount; i++) {
								System.out.println("delete " + i);
								File f = new File(Environment.getExternalStorageDirectory(), i + ".txt");
								f.delete();
							}
							finishedThread = 0;
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开始下载"
        android:onClick="click"
        />
</RelativeLayout>

配置文件添加权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值