android实用方法- - - -断点续传详解
最近遇到一点小需求,音乐下载,需要暂停下载,由于之前没有写过也是找了一些资源才搞懂的O(∩_∩)O哈哈~
首先要明确一点这个是需要后台支持的,也就是后台必须提供我们可以在某个字节开始下载的接口
下面我给大家说下基本思路,首先我们需要暂停下载,也就是我们需要在下载线程中中断下载,这个需要广播。然后就是我们的断点位置需要保存,所以我们需要实体类,并且我们需要存放在sqlite中方便增删改查。然后暂停之后我们从sqlite中取出上次的断点,向服务器请求实现断点下载。并且,在当前的文件的字节后开始下载实现断点续传。
如上图所示基本上整个程序的逻辑
简答说下几个重要的点吧
首先你要有个保存当前下载位置的实体类
代码块
代码块语法遵循标准markdown代码,例如:
package com.example.nick.downloaddemo.entity;
/**
* Created by Nick on 2017/2/7.
* 线程信息
*/
public class ThreadInfo {
private int id;
private String url;
private int start;//线程从哪里开始下载
private int end;//下载到哪里结束
private int finished;//完成了多少
public ThreadInfo() {
}
public ThreadInfo(int id, String url, int start, int end, int finished) {
this.id = id;
this.url = url;
this.start = start;
this.end = end;
this.finished = finished;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getFinished() {
return finished;
}
public void setFinished(int finished) {
this.finished = finished;
}
@Override
public String toString() {
return "ThreadInfo{" +
"id=" + id +
", url='" + url + '\'' +
", start=" + start +
", end=" + end +
", finished=" + finished +
'}';
}
}
下面就需要sqlite来存储这些信息这个我就不贴了
然后你需要暂停下载 判断条件是传过来的 保存方法时工具类写好的
// 在下载暂停时,保存下载进度 终止下载
if (isPause)
{
mDao.updateThread(mThreadInfo.getUrl(), mThreadInfo.getId(), mFinised);
return;
}
最重也要的就是下载代码这里给出,就是不存在就创建,存在就取出
public void downLoad()
{
// 读取数据库的线程信息
List<ThreadInfo> threads = mDao.getThreads(mFileInfo.getUrl());
ThreadInfo threadInfo = null;
if (0 == threads.size())
{
// 初始化线程信息对象
threadInfo = new ThreadInfo(0, mFileInfo.getUrl(),
0, mFileInfo.getLength(), 0);
}
else
{
threadInfo = threads.get(0);
}
// 创建子线程进行下载
new DownloadThread(threadInfo).start();
}/**
* 下载线程 这里是断点续传的关键之一
* @author Yann
* @date 2015-8-8 上午11:18:55
*/
private class DownloadThread extends Thread
{
private ThreadInfo mThreadInfo = null;/**
*@param mInfo
*/
public DownloadThread(ThreadInfo mInfo)
{
this.mThreadInfo = mInfo;
}
/**
* @see java.lang.Thread#run()
*/
@Override
public void run()
{
// 向数据库插入线程信息
if (!mDao.isExists(mThreadInfo.getUrl(), mThreadInfo.getId()))
{
mDao.insertThread(mThreadInfo);
}
HttpURLConnection connection = null;
RandomAccessFile raf = null;
InputStream inputStream = null;
try
{
URL url = new URL(mThreadInfo.getUrl());
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
// 设置下载位置
int start = mThreadInfo.getStart() + mThreadInfo.getFinished();
Log.e("下载的位置",start+"");
//设置下开始位置到结束的位置 setRequestProperty主要是设置HttpURLConnection请求头里面的属性 这个主要是看后台怎么写
connection.setRequestProperty("Range",
"bytes=" + start + "-" + mThreadInfo.getEnd());
// 设置文件写入位置
File file = new File(DownloadService.DOWNLOAD_PATH,
mFileInfo.getFilename());
raf = new RandomAccessFile(file, "rwd");
//设置开始下载的位置 这是设置跳过多少个字节开始写入文件夹 例如raf.seek(10);就是跳过10个字节从11个字节开始
raf.seek(start);
Intent intent = new Intent();
intent.setAction(DownloadService.ACTION_UPDATE);
mFinised += mThreadInfo.getFinished();
// 开始下载
if (connection.getResponseCode() == 206)
{
// 读取数据
inputStream = connection.getInputStream();
byte buf[] = new byte[1024<<2];
int len = -1;
long time = System.currentTimeMillis();
while ((len = inputStream.read(buf)) != -1)
{
// 写入文件
raf.write(buf, 0, len);
// 把下载进度发送广播给Activity
mFinised += len;
if (System.currentTimeMillis() - time > 500)
{
Log.i("file——Start","发送广播");
time = System.currentTimeMillis();
intent.putExtra("finished", mFinised * 100 / mThreadInfo.getEnd());
mContext.sendBroadcast(intent);
}
// 在下载暂停时,保存下载进度 终止下载
if (isPause)
{
mDao.updateThread(mThreadInfo.getUrl(), mThreadInfo.getId(), mFinised);
return;
}
}
//最后一次可能小于500导致最后一次广播发不出去,进而不能显示完成100%
Log.i("file——Start","发送广播");
intent.putExtra("finished", mFinised * 100 / mThreadInfo.getEnd());
mContext.sendBroadcast(intent);
// 删除线程信息
mDao.deleteThread(mThreadInfo.getUrl(), mThreadInfo.getId());
Log.i("DownloadTask", "下载完毕");
MainActivity.mMainActivity.handler.sendEmptyMessage(0);
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if (connection != null)
{
connection.disconnect();
}
if (raf != null)
{
raf.close();
}
if (inputStream != null)
{
inputStream.close();
}
}
catch (Exception e2)
{
e2.printStackTrace();
}
}
}
}
以上就是下载的代码,上注释很清楚
// 设置下载位置
int start = mThreadInfo.getStart() + mThreadInfo.getFinished();
Log.e(“下载的位置”,start+”“);
//设置下开始位置到结束的位置 setRequestProperty主要是设置HttpURLConnection请求头里面的属性 这个主要是看后台怎么写
connection.setRequestProperty(“Range”,
“bytes=” + start + “-” + mThreadInfo.getEnd());// 设置文件写入位置
File file = new File(DownloadService.DOWNLOAD_PATH,
mFileInfo.getFilename());
raf = new RandomAccessFile(file, “rwd”);
//设置开始下载的位置 这是设置跳过多少个字节开始写入文件夹 例如raf.seek(10);就是跳过10个字节从11个字节开始
raf.seek(start);
这就实现了文件的断点拼接
这里会给出源码希望能帮助到你们( ⊙ o ⊙ )!