Android中多线程下载

public class MainActivity extends Activity {

	// 声明控件
	// 路径与线程数量
	private EditText et_url, et_num;
	// 进度条
	public static ProgressBar pb_thread;
	// 显示进度的操作
	private TextView tv_pb;

	// 线程的数量
	public static int threadNum = 3;
	// 每个线程负责下载的大小
	public int blockSize;

	public static int threadCount;// 数量

	// 访问的path
	public String path;

	public static boolean flag = true;

	// 记录进度条的值
	public static int pb_count = 0;

	public static Handler handler;

	public static final int TEXTVALUE = 1;

	public static int pb_num = 0;
	public static int size = 0;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		et_url = (EditText) findViewById(R.id.et_path);
		et_num = (EditText) findViewById(R.id.et_threadNum);
		pb_thread = (ProgressBar) findViewById(R.id.pb_down);
		tv_pb = (TextView) findViewById(R.id.tv_pb);

		handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case TEXTVALUE:
					System.out.println("-----------------------"
							+ MainActivity.pb_count + "//"
							+ MainActivity.size);
				
					// 改变TEXTView
					pb_num = (MainActivity.pb_count * 100) / MainActivity.size;
					tv_pb.setText("当前进度是+" + pb_num + "%");
					break;

				default:
					break;
				}
			}
		};

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
	//	getMenuInflater().inflate(R.menu.down, menu);
		return true;
	}

	//下载操作
	public void downLoad(View v) {

		// 改变变量值:
		MainActivity.flag = true;
		MainActivity.pb_count = 0;

		path = et_url.getText().toString();
		String threadNum_et = et_num.getText().toString();
		if (TextUtils.isEmpty(path) || TextUtils.isEmpty(threadNum_et)) {
			Toast.makeText(this, "不能为空", Toast.LENGTH_LONG).show();
			return;
		}

		Toast.makeText(this, "url:" + path + "--" + threadNum_et,
				Toast.LENGTH_LONG).show();

		// 转换成数字
		threadNum = Integer.valueOf(threadNum_et);

		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					// 创建出URL对象
					URL url = new URL(path);
					// 创建出 HttpURLConnection对象
					HttpURLConnection httpURLConnection = (HttpURLConnection) url
							.openConnection();

					// 设置 发请求发送的方式
					httpURLConnection.setRequestMethod("GET");
					// 设置请求是否超时时间
					httpURLConnection.setConnectTimeout(5000);
					// 设置
					httpURLConnection
							.setRequestProperty("User-Agent",
									" Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");

					// 是否响应成功
					if (httpURLConnection.getResponseCode() == 200) {
						// 获取文件的大小
						size = httpURLConnection.getContentLength();
						System.out.println("文件的大小" + size);
						// 设置进度条的最大值
						pb_thread.setMax(size);

						// 创建文件 //保存到SD卡上

						// 首先判断是否拥有sdcard
						if (Environment.getExternalStorageState().equals(
								Environment.MEDIA_MOUNTED)) {
							// 获取sdCard文件目录对象
							File sdFile = Environment
									.getExternalStorageDirectory();
							// 创建文件对象
							File file = new File(sdFile, "youdao.exe");

							RandomAccessFile accessFile = new RandomAccessFile(
									file, "rwd");
							// 设置文件的大小
							accessFile.setLength(size);
							// 每个线程下载的大小
							blockSize = size / threadNum;
							// 开三个线程 操作此文件
							for (int i = 1; i <= threadNum; i++) {
								// 1 2 3
								// 计算出每个线程开始的位置
								int startSize = (i - 1) * blockSize;
								// 结束位置
								int endSize = (i) * blockSize;
								// 当线程是最后一个线程的时候
								if (i == threadNum) {
									// 判断文件的大小是否大于计算出来的结束位置
									if (size > endSize) {
										// 结束位置 等于 文件的大小
										endSize = size;
									}
								}
								// 为每个线程创建一个随机的读取
								RandomAccessFile threadAccessFile = new RandomAccessFile(
										file, "rwd");
								new Thread(new DownLoadThread(i,
										threadAccessFile, startSize, endSize,
										path)).start();
							}

						}

					}

				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}).start();

	}

	//暂停操作
	public void downPause(View v) {
		Toast.makeText(this, "暂停", Toast.LENGTH_LONG).show();

		this.flag = false;

	}
}



public class DownLoadThread implements Runnable {

	// 下载文件的封装
	public RandomAccessFile accessFile; 

	// 线程下载文件的起始位置
	public int startSize;
	public int endSize;

	// 文件下载的path路径
	public String path;

	public int threadId; // 线程的标识

	public DownLoadThread(int threadId, RandomAccessFile accessFile,
			int startSize, int endSize, String path) {

		this.threadId = threadId;
		this.accessFile = accessFile;
		this.startSize = startSize;
		this.endSize = endSize;
		this.path = path;
	}

	@Override
	public void run() {
		// 执行run方法
		try {

			// 创建文件到SD卡上去

			// 首先判断是否拥有sdcard
			if (Environment.getExternalStorageState().equals(
					Environment.MEDIA_MOUNTED)) {
				// 获取sdCard文件目录对象
				File sdFile = Environment.getExternalStorageDirectory();
				File threadFile = new File(sdFile, threadId + ".txt");

				if (threadFile.exists()) {

					// 读取该文件的内容
					// 创建文件的输入流对象
					FileInputStream fis = new FileInputStream(threadFile);
					// 采用工具类读取
					byte data[] = StreamTools.isToData(fis);
					// 转化成字符串
					String threadLen = new String(data);

					if ((threadLen != null) && (!"".equals(threadLen))) {
						startSize = Integer.valueOf(threadLen);

						// 解决 416bug的错误
						if (startSize > endSize) {
							startSize = endSize - 1;
						}
					}

				}

				// 创建文件

				// 创建URL对象
				URL url = new URL(path);
				// 创建HttpURLConnection对象
				HttpURLConnection httpURLConnection = (HttpURLConnection) url
						.openConnection();
				// 设置请求的头

				httpURLConnection.setRequestMethod("GET");
				// 设置请求是否超时时间
				httpURLConnection.setConnectTimeout(5000);
				// 设置
				httpURLConnection
						.setRequestProperty("User-Agent",
								" Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");

				// 关键的设置
				httpURLConnection.setRequestProperty("Range", "bytes="
						+ startSize + "-" + endSize);

				// 输出当前线程
				System.out.println("当前线程" + threadId + " 下载开始位置:" + startSize
						+ " 下载结束位置:" + endSize);
				// 响应成功

				// 设置随机读取文件的 开始位置
				accessFile.seek(startSize);
				// 获取相应流对象
				InputStream is = httpURLConnection.getInputStream();
				// 创建输出流对象

				byte buffer[] = new byte[1024];
				int len = 0;
				int threadTotal = 0;// 每个线程下载后保存记录 /
				while ((len = is.read(buffer)) != -1) {
					accessFile.write(buffer, 0, len);
					threadTotal += len;// 记录你写入的长度 //xml文件

					//改变进度条:
					setProgressBar(len);
					// 通过文件记录文件下载的长度
					FileOutputStream fos = new FileOutputStream(threadFile);
					fos.write((threadTotal + "").getBytes());
					fos.flush();
					fos.close();
					//发送handler消息
					MainActivity.handler.sendEmptyMessage(MainActivity.TEXTVALUE);
					if(!MainActivity.flag){
						return;
					}

				}
				accessFile.close();
				is.close();
				System.out.println(threadId + "线程执行完毕");

				// 线程操作
				synchronized (MainActivity.class) {
					MainActivity.threadCount++;
					if (MainActivity.threadCount >= MainActivity.threadNum) {
						for (int i = 1; i <= MainActivity.threadNum; i++) {
							// 获取sdCard上的文件
							File deleteFile = new File(sdFile, i + ".txt");
							if (deleteFile.exists()) {
								// 文件删除
								deleteFile.delete();
							}
						}
					}
				}
			}
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	
	
	
	public synchronized void setProgressBar(int len){
		MainActivity.pb_count+=len;
		MainActivity.pb_thread.setProgress(MainActivity.pb_count);
	}
	
	
	
}

public class StreamTools {

	
	public static byte[] isToData(InputStream is) throws IOException{
		// 字节输出流
		ByteArrayOutputStream bops = new ByteArrayOutputStream();
		// 读取数据的缓存区
		byte buffer[] = new byte[1024];
		// 读取长度的记录
		int len = 0;
		// 循环读取
		while ((len = is.read(buffer)) != -1) {
			bops.write(buffer, 0, len);
		}
		// 把读取的内容转换成byte数组
		byte data[] = bops.toByteArray();
		
		bops.flush();
		bops.close();
		is.close();
		return data;
	}
}

完整源码请访问:http://download.csdn.net/detail/chrp99/5616629

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值