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(当前值);