Android 使用HttpURLConnection实现多线程下载 笔记
2014-03-31 20:20
603 查看
参考阅读文章:
http://www.tuicool.com/articles/7bEJFv
使用HttpURLConnection实现多线程下载 核心步骤:
*****************源代码及注释****************
DownUtil.java
MultiThreadDown.java
activity_multi_thread_down.xml
***********************************************
注释:
1.核心代码:
首先创建一个文件指针file指向将要写的文件,设置该文件的大小,然后关闭该文件指针。
接着在创建不同线程的for()循环中让不同线程的new currentPart文件指针指向该文件的不同部分;让不同线程写该文件的不同部分。
2.核心Java IO API支持:
(1)
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte
数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过
构造方法:
RandomAccessFile
创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
方法摘要
void seek(long pos)
设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。
void write(byte[] b, int off, int len)
将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。
void setLength(long newLength)
设置此文件的长度。
(2)
java.io
类 InputStream
long skip(long n)
跳过和丢弃此输入流中数据的 n 个字节。
3. 计算每条线程需要下载的数据长度的原理及影响的详细分析:
* 1 如果资源大小模于线程数时结果为0,那么表示每条线程需要下载的大小恰好将原大小等分
* 2 当然更多的情况是有余数的(即不能整除).那么此时该怎么办呢?每条线程该下载的长度是多少呢?
* 我们可以这么做:
(1)原大小/除以线程的条数
(2) 在1的基础上+1
这样就表示每条线程要下载的大小长度
4.需要添加的相关权限
<!-- 在SD卡中创建与删除文件权限-->
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--向SD卡写入数据权限 -->
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--授权访问网络 -->
<uses-permissionandroid:name="android.permission.INTERNET"/>
5.注意:
线程中不能处理UI操作 比如toast
要处理UI操作都只能通知Handler 更新用户UI界面
http://www.tuicool.com/articles/7bEJFv
使用HttpURLConnection实现多线程下载 核心步骤:
*****************源代码及注释****************
DownUtil.java
package com.example.multithreaddown; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class DownUtil { private String path; private String targetFile; private int ThreadNum; private DownThread[] threads;//downthread object array private int total_filesize;//get length , calculate down percentage public DownUtil(String path,String targetFile,int ThreadNum){//outclass constructor this.path = path; this.targetFile = targetFile; this.ThreadNum = ThreadNum; threads = new DownThread[ThreadNum];//initial download object array } //main download method create each downthread object public void download() throws Exception{ URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); // conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.setRequestProperty( "Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8");//**UTF-8***in android platform conn.setRequestProperty("Connection", "Keep-Alive"); // total_filesize = conn.getContentLength(); conn.disconnect(); RandomAccessFile file = new RandomAccessFile(targetFile,"rw"); file.setLength(total_filesize); file.close(); int currentPartSize = total_filesize/ThreadNum + 1; int startPos = 0; //create each download thread for(int i = 0;i<ThreadNum;i++){ startPos = i*currentPartSize; //*** RandomAccessFile currentPart = new RandomAccessFile(targetFile,"rw"); currentPart.seek(startPos); threads[i] = new DownThread(startPos,currentPartSize,currentPart); // threads[i].start();// } } public double getCompleteRate(){ int sumSize = 0; for(int i = 0;i<ThreadNum;i++){ //calculate the already download amount of each thread sumSize += threads[i].download_length; } return (sumSize*1.0)/total_filesize; } //Inner thread class private class DownThread extends Thread{ // private int startPos; private int currentPartSize; private RandomAccessFile currentPart; public int download_length = 0;//calculate percentage in outer class method //inner class constructor public DownThread(int startPos,int currentPartSize,RandomAccessFile currentPart){ this.startPos = startPos; this.currentPartSize = currentPartSize; this.currentPart = currentPart; } @Override public void run(){ try{ URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); // conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.setRequestProperty( "Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); // InputStream inStream = conn.getInputStream(); inStream.skip(startPos);// byte []buffer = new byte[1024]; int hasRead = 0; // // while((download_length<=currentPartSize)&&(hasRead = inStream.read(buffer))!=-1){ while((download_length<currentPartSize)&&(hasRead = inStream.read(buffer))!=-1){ currentPart.write(buffer, 0, hasRead);// download_length += hasRead; } currentPart.close(); inStream.close(); }catch(Exception e){ e.printStackTrace(); } } } }
MultiThreadDown.java
package com.example.multithreaddown; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class DownUtil { private String path; private String targetFile; private int ThreadNum; private DownThread[] threads;//downthread object array private int total_filesize;//get length , calculate down percentage public DownUtil(String path,String targetFile,int ThreadNum){//outclass constructor this.path = path; this.targetFile = targetFile; this.ThreadNum = ThreadNum; threads = new DownThread[ThreadNum];//initial download object array } //main download method create each downthread object public void download() throws Exception{ URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); // conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.setRequestProperty( "Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8");//**UTF-8***in android platform conn.setRequestProperty("Connection", "Keep-Alive"); // total_filesize = conn.getContentLength(); conn.disconnect(); RandomAccessFile file = new RandomAccessFile(targetFile,"rw"); file.setLength(total_filesize); file.close(); int currentPartSize = total_filesize/ThreadNum + 1; int startPos = 0; //create each download thread for(int i = 0;i<ThreadNum;i++){ startPos = i*currentPartSize; //*** RandomAccessFile currentPart = new RandomAccessFile(targetFile,"rw"); currentPart.seek(startPos); threads[i] = new DownThread(startPos,currentPartSize,currentPart); // threads[i].start();// } } public double getCompleteRate(){ int sumSize = 0; for(int i = 0;i<ThreadNum;i++){ //calculate the already download amount of each thread sumSize += threads[i].download_length; } return (sumSize*1.0)/total_filesize; } //Inner thread class private class DownThread extends Thread{ // private int startPos; private int currentPartSize; private RandomAccessFile currentPart; public int download_length = 0;//calculate percentage in outer class method //inner class constructor public DownThread(int startPos,int currentPartSize,RandomAccessFile currentPart){ this.startPos = startPos; this.currentPartSize = currentPartSize; this.currentPart = currentPart; } @Override public void run(){ try{ URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); // conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.setRequestProperty( "Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); // InputStream inStream = conn.getInputStream(); inStream.skip(startPos);// byte []buffer = new byte[1024]; int hasRead = 0; // // while((download_length<=currentPartSize)&&(hasRead = inStream.read(buffer))!=-1){ while((download_length<currentPartSize)&&(hasRead = inStream.read(buffer))!=-1){ currentPart.write(buffer, 0, hasRead);// download_length += hasRead; } currentPart.close(); inStream.close(); }catch(Exception e){ e.printStackTrace(); } } } }
activity_multi_thread_down.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="下载资源的URL:" /> <EditText android:id="@+id/url" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="http://zhangmenshiting.baidu.com/data2/music/108215782/14385500158400128.mp3?xcode=403698f0ca4477d527224dddfa01e691cc816ddc4bb4461a" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="目标文件:" /> <EditText android:id="@+id/target" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="/mnt/sdcard/时间都去哪儿了.mp3" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="线程数:" /> <NumberPicker android:id="@+id/np_thread" android:layout_width="match_parent" android:layout_height="80dp" android:focusable="true" android:focusableInTouchMode="true" /> <Button android:id="@+id/down" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="下载" /> <!-- 定义一个水平进度条,用于显示下载进度 --> <ProgressBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_height="20dp" android:max="100" style="?android:attr/progressBarStyleHorizontal" /> </LinearLayout>
***********************************************
注释:
1.核心代码:
首先创建一个文件指针file指向将要写的文件,设置该文件的大小,然后关闭该文件指针。
接着在创建不同线程的for()循环中让不同线程的new currentPart文件指针指向该文件的不同部分;让不同线程写该文件的不同部分。
2.核心Java IO API支持:
(1)
public class RandomAccessFile
extends Object
implements DataOutput, DataInput, Closeable
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte
数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过
getFilePointer方法读取,并通过
seek方法设置。
构造方法:
RandomAccessFile
(String
name,String
mode)
创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
方法摘要
void seek(long pos)
设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。
void write(byte[] b, int off, int len)
将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。
void setLength(long newLength)
设置此文件的长度。
(2)
java.io
类 InputStream
long skip(long n)
跳过和丢弃此输入流中数据的 n 个字节。
3. 计算每条线程需要下载的数据长度的原理及影响的详细分析:
* 1 如果资源大小模于线程数时结果为0,那么表示每条线程需要下载的大小恰好将原大小等分
* 2 当然更多的情况是有余数的(即不能整除).那么此时该怎么办呢?每条线程该下载的长度是多少呢?
* 我们可以这么做:
(1)原大小/除以线程的条数
(2) 在1的基础上+1
这样就表示每条线程要下载的大小长度
4.需要添加的相关权限
<!-- 在SD卡中创建与删除文件权限-->
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--向SD卡写入数据权限 -->
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--授权访问网络 -->
<uses-permissionandroid:name="android.permission.INTERNET"/>
5.注意:
线程中不能处理UI操作 比如toast
要处理UI操作都只能通知Handler 更新用户UI界面
相关文章推荐
- Android 使用HttpURLConnection 实现多线程下载
- android中使用HttpURLConnection实现多线程下载
- Android-使用HttpURLConnection实现多线程下载
- Android开发_使用HttpURLConnection实现多线程下载
- 使用HttpURLConnection实现在android客户端和服务器之间传递对象
- Android移动开发-使用HttpURLConnection和AsyncTask请求解析地理位置实现
- Android上Java网络资源访问(二)使用HttpURLConnection多线程下载
- Android 4.4以上使用HttpURLConnection底层使用OkHttp实现的源码分析
- android使用HttpURLConnection实现带参数文件上传
- Android Http协议笔记(使用HttpURLConnection)文件上传+参数
- android客户端通过Get方式提交参数给服务器,使用URL和HttpURLConnection实现,以及乱码问题解决
- Android Http协议笔记(使用HttpURLConnection)文件上传+参数
- Android 中使用HttpUrlConnection实现get请求服务器
- 【Android进阶】使用HttpURLConnection实现图片的下载与现显示
- Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
- 使用HttpURLConnection实现在android客户端和服务器之间传递对象
- Android中如何使用HttpURLConnection实现GET POST JSON数据与下载图片
- Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
- Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
- 使用HttpURLConnection实现多线程下载