1、HttpURLConnection

2、httpClient API23以后,就没有HttpClient了

在文件 build.gradle 中android{ 下添加下面的内容

useLibrary 'org.apache.http.legacy'

清单文件中添加

android:name="org.apache.http.legacy"

android:required="false"/>

3、其他开源工具 okhttp、asynchttpclient

在AndroidStudio中使用不需要下载jar包,直接添加依赖即可:

compile ‘com.squareup.okhttp3:okhttp:3.4.1’

4、多线程下载文件

【1】获取服务器文件的大小

HttpURLConnection conn = url.openConnection()

long fileSize = conn.getContentLength();

【2】在客户端创建一个大小与服务器文件一样的文件,提前请求空间

需要随机的访问文件的读取和写入,使用RandomAccessFile

//模式 r 只读,rw读写,rws 写入元数据并同步到硬盘 rwd不同步写入元数据

RandomAccessFile raf = new RandomAccessFile("文件名","模式")

raf.setLength(fileSize);//设置文件的大小

【3】计算每个线程下载文件的开始位置和结束位置

计算思路:

private static final int threadCount = 3; //定义默认开启三个线程

//每个线程下载文件的大小

第八部分 网络编程进度条_下载文件

文件大小(10)/线程数(3) = 每个线程下载的大小(3)(blockSize)

设n为线程下标,则每个线程的下载大小

n*blockSize ~ (n+1)*blockSize-1

0*3 ~ 1*3-1 0~2

1*3 ~ 2*3-1 3~5

最后一个线程下载为m,则m

m*blockSize ~ fileSize(10)-1

2*3 9 6~9

代码实现:

int blockSize = fileSize/threadCount;

for(int i=0;i

long startIndex = i*blockSize; //下载文件的开始位置

long endIndex = (i+1)*blockSize-1;//下载文件的接收位置

//最后一个线程

if(i=threadCount-1){

endIndex = fileSize-1;

}

//开启线程下载文件

new DownLoadFile(startIndex,endIndex).start;

}

【4】开启线程下载需要下载的部分

public class DownLoadFile extends Thread{

private long startIndex ;

private long endIndex;

private int threadId;

public DownLoadFile(long startIndex,long endIndex,int threadId){

this.startIndex = startIndex;

this.endIndex = endIndex;

this.threadId = threadId;

}

@Override

public void run(){

//创建URL

URL url = new URL("");

//建立链接

HttpURLConnection conn = (HttpURLConnection)url.openConnection();

//设置请求方式

conn.setRequestMethod("get");

//设置超时

conn.setConnectTimeout(5000);

//断点续传的逻辑

//从文件中读取上次保存的位置

File file = new FIle(threadId+".txt");

if(file.exit()&&file.length()>0){

FileInputStream in = new FileInputStream(file);

BufferReader buff = new BufferReader(new InputStreamReader(in));

String lastPosition = buff.readLine();

startIndex = Integer.parseInt(lastPosition);//开始位置为上次的

in.close();

}

//设置请求头

conn.setRequestProperty("Range","bytes="+startIndex+"-"+endIndex);

//获取返回码

int code = conn.getResponseCode();

if(206==code){ //请求资源部分成功

//将请求的结果写入本地文件

//创建随机读取的文件对象

RandomAccessFile raf = new RandomAccessFile("fileName.ext","rwd");

//从开始位置开始写入

raf.seek(startIndex);

//获取服务器文件的流,写入文件

InputStream in = conn.getInputStream();

int leg = -1;

byte[] bytes = new byte[1024*1024*5]; //缓存区设置5M

//断点续传

long total = 0;//当前线程下载的大小

while((leg=in.read(bytes))!=-1){

raf.write(leg);

total += leg;

//当前下载的位置存起来,下次下载的时候就是按照上次下载的位置继续下载

int currentThreadPosition = startIndex+total; //将这个位置存起来

//注意使用fos.write()方法有问题,该方法不会同步到底层,先同步到硬盘缓存。使用RandomAccessFile类的rwd模式直接同步的硬盘底层

File positionTxt = new File(threadId+".txt");

FileOutputStream fos = new FileOutPutStream(file);

fos.write(String.valueOf(currentThreadPosition.getByte()))

fos.close();

}

//关闭流

raf.close();

//断点续传,下载完毕删除位置文件,注意加入锁

synchronized(DownLoadFile .class){

//删除位置文件

}

}

}

5、开源项目多线程下载 Xutils

6、动态添加进度条

【1】添加进度条的布局


【2】添加进度条的布局到active

View progressBar = View.inflate(Contex,R.layout.progressBar,null)

LinerLayout.addView(progressBar);

【3】设置进度调的最大值和当前位置

progressBar.setMax(最大值);

progressBar.setPressed(当前值);