实现步骤:
1. 开启服务 + 新线程获取文件大小
2. 获取文件大小后 开启新线程 开始下载 在下载之前先查询数据库是否有该条“下载URL“的下载记录 如果有获取断点位置 继续下载 如果没有则按新文件下载。
3.所使用到的新内容:RandomAccess 特殊的输出流 可以在任意位置进行写入操作 。在第一次获取文件大小时 判断状态为HttpURLConnection.HTTP_OK(200)
文件下载时 需使用HttpUlRLConnection.HTTP_PARTIAL(206)
MainActivity Code
@Override
public void onClick(View view) {
intent =new Intent(this,DownLoadService.class);
switch (view.getId()){
case R.id.down:
intent.setAction(DownLoadService.ACTION_START);
intent.putExtra("fileinfo",fileInfo);
startService(intent);
break;
case R.id.pause:
intent.setAction(DownLoadService.ACTION_STOP);
intent.putExtra("fileinfo",fileInfo);
startService(intent);
break;
}
}
/*
* 根据广播传入的进度 更新UI进度值
* */
BroadcastReceiver receiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(DownLoadService.ACTION_UPDATE)){
int finished = intent.getIntExtra("finished",0);
progressBar.setProgress(finished);
}
}
};
DownLoadService Code
public class DownLoadService extends Service {
public static final String DOWN_LOAD_PATCH = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"download"+File.separator;
public static final String ACTION_START="ACTION_START";
public static final String ACTION_STOP="ACTION_STOP";
public static final String ACTION_UPDATE="ACTION_UPDATE";
public static final int MSG_INIT = 001;
public DownLoadTask task;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
FileInfo fileInfo= (FileInfo) intent.getSerializableExtra("fileinfo");
//启动初始化线程
if(intent.getAction().equals(ACTION_START)){
new InitThread(fileInfo).start();
}
//停止下载
if(intent.getAction().equals(ACTION_STOP)){
if(task!=null){
task.isPause=true;
}
}
return super.onStartCommand(intent, flags, startId);
}
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_INIT:
FileInfo fileInfo = (FileInfo) msg.obj;
//启动下载任务
task=new DownLoadTask(DownLoadService.this,fileInfo);
task.download();
break;
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
}
class InitThread extends Thread{
public FileInfo fileinfo;
public InitThread(FileInfo fileInfo){
this.fileinfo=fileInfo;
}
@Override
public void run() {
//连接网络文件 获取文件长度后 本地创建文件长度
HttpURLConnection urlConnection=null;
RandomAccessFile randomAccessFile=null;
URL url= null;
try {
url = new URL(fileinfo.getUrl());
urlConnection=(HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(3000);
urlConnection.setConnectTimeout(5000);
urlConnection.setDoOutput(true);
int length=-1;
if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){
//获取文件长度
length=urlConnection.getContentLength();
}
if(length<0){
return ;
}
File dir=new File(DOWN_LOAD_PATCH);
//判断路径是否存在
if(!dir.exists()){
//如果不存在就创建
dir.mkdir();
}
File file=new File(dir,fileinfo.getFilename());
//特殊输出流 在任意位置进行写入操作 方面后面的断点续传
randomAccessFile=new RandomAccessFile(file,"rwd");
//设置文件长度
randomAccessFile.setLength(length);
fileinfo.setLength(length);
//通过该线程获取到文件长度后 调用下载进程
handler.obtainMessage(MSG_INIT,fileinfo).sendToTarget();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
urlConnection.disconnect();
try {
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
DownLoadTask Code
public class DownLoadTask {
public Context context;
public FileInfo fileInfo;
public DB_interface db;
public boolean isPause=false;
public DownLoadTask(Context context, FileInfo fileInfo) {
this.context = context;
this.fileInfo = fileInfo;
db=new db_manager(context);
}
public void download(){
//读取数据库的线程信息
List<ThreadInfo> threadInfos = db.getThreads(fileInfo.getUrl());
System.out.println(threadInfos);
ThreadInfo threadInfo=null;
if(threadInfos.size()==0){
//初始化线程信息对象
threadInfo=new ThreadInfo(fileInfo.getLength(),0,fileInfo.getId(),0,fileInfo.getUrl(),fileInfo.getFilename());
}else{
threadInfo=threadInfos.get(0);
}
DownLoadThread downLoadThread=new DownLoadThread(threadInfo);
downLoadThread.start();
}
//下载线程
class DownLoadThread extends Thread{
private ThreadInfo threadInfo;
private HttpURLConnection connection;
private int mFinished=0;
private InputStream inputStream;
private RandomAccessFile randomAccessFile;
public DownLoadThread(ThreadInfo threadInfo) {
this.threadInfo = threadInfo;
}
@Override
public void run() {
//数据库插入线程下载信息
if(!db.isExists(threadInfo.getUrl(), threadInfo.getId())){
//如果不存在 则向数据库插入数据
db.insertThread(threadInfo);
}
try {
URL url=new URL(threadInfo.getUrl());
connection=(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
//设置下载位置
int start= threadInfo.getStart()+ threadInfo.getFinished();
System.out.println("start===="+threadInfo.getFinished());
long time = System.currentTimeMillis();
connection.setRequestProperty("Range","bytes="+start+"-"+ threadInfo.getEnd());
//设置文件写入文职
File file=new File(DownLoadService.DOWN_LOAD_PATCH+ threadInfo.getName());
randomAccessFile=new RandomAccessFile(file,"rw");
randomAccessFile.seek(start);
Intent intent=new Intent(DownLoadService.ACTION_UPDATE);
mFinished+= threadInfo.getFinished();
//开始下载
if(connection.getResponseCode()==HttpURLConnection.HTTP_PARTIAL){
//读取数据
inputStream= connection.getInputStream();
byte[] bytes=new byte[3*1024];
int len=-1;
while ((len=inputStream.read(bytes))!=-1){
//读取数据 开始下载
randomAccessFile.write(bytes,0,len);
//下载进度广播为activity
mFinished+=len;
//判断时间差 发送广播通知
if(System.currentTimeMillis()-time>500){
time=System.currentTimeMillis();
intent.putExtra("finished",mFinished*100/ fileInfo.getLength());
context.sendBroadcast(intent);
}
if(isPause){
//暂停下载
System.out.println("pause "+mFinished);
db.updateThread(threadInfo.getUrl(),threadInfo.getId(),mFinished);
return;
}
}
//删除线程信息
db.deleteThread(threadInfo.getUrl(),threadInfo.getId());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
connection.disconnect();
try {
inputStream.close();
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}