安卓(android)之实现断点下载功能
一.建立实体类 1.文件实体类 package com.example.zjw.myapplication.dao; import java.io.Serializable; /**
* 预下载文件实体类
* Created by Administrator on 2016/6/20.
*/
public class FileInfo implements Serializable {
//文件id
private int id;
//文件下载地址
private String url;
//文件名
private String name;
//文件长度
private int length;
//文件下载完成进度
private int finished; public FileInfo(){}
public FileInfo(int id, String url, String name, int length, int finished) {
this.id = id;
this.url = url;
this.name = name;
this.length = length;
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 String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getLength() {
return length;
} public void setLength(int length) {
this.length = length;
} public int getFinished() {
return finished;
} public void setFinished(int finished) {
this.finished = finished;
} @Override
public String toString() {
return "FileInfo{" +
"id=" + id +
", url='" + url + '\'' +
", name='" + name + '\'' +
", length=" + length +
", finished=" + finished +
'}';
}
} 2.线程实体类
package com.example.zjw.myapplication.dao; import java.io.Serializable; /**下载线程实体类
* Created by Administrator on 2016/6/20.
*/
public class ThreadInfo implements Serializable{ //线程id
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 +
'}';
}
}
二、建立数据库 1.建立数据库帮助类
package com.example.zjw.myapplication.db; import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; /**数据库帮助类
* Created by Administrator on 2016/6/20.
*/
public class DBHelper extends SQLiteOpenHelper { //数据库名称
private static final String DB_NAME="download.db";
//数据库版本
private static final int VERSION=1;
//创建数据库表sql语句
private static final String SQL_CREATE="create table thread_info(id integer primary key autoincrement,thread_id integer,url text,start integer,end integer,finished integer)";
//删除数据库表语句
private static final String SQL_DROP="drop table if exists thread_info"; public DBHelper(Context context) {
super(context,DB_NAME,null,VERSION);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DROP);
}
}
2.建立数据库访问接口
package com.example.zjw.myapplication.db; import com.example.zjw.myapplication.dao.ThreadInfo; import java.util.List; /**
* 数据访问接口
* Created by Administrator on 2016/6/20.
*/
public interface ThreadDao { void addThreadInfo(ThreadInfo threadInfo);
void deleteThreadInfo(String url,int thread_id);
void updateThreadInfo(String url,int thread_id,int finished);
List<ThreadInfo>getThreadInfo(String url);
boolean findThreadInfo(String url,int thread_id);
}
3.实现数据库访问接口
package com.example.zjw.myapplication.db; import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log; import com.example.zjw.myapplication.dao.ThreadInfo; import java.util.ArrayList;
import java.util.List; /**数据库接口访问实现
* Created by Administrator on 2016/6/20.
*/
public class ThreadDaoImpl implements ThreadDao { private DBHelper dbHelper =null; public ThreadDaoImpl(Context context) {
this.dbHelper = new DBHelper(context);
} @Override
public void addThreadInfo(ThreadInfo threadInfo) { SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
writableDatabase.execSQL("insert into thread_info(thread_id,url,start,end,finished) values(?,?,?,?,?)",new Object[]{
threadInfo.getId(),threadInfo.getUrl(),threadInfo.getStart(),threadInfo.getEnd(),threadInfo.getFinished()});
writableDatabase.close();
}
@Override
public void deleteThreadInfo(String url, int thread_id) {
SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
writableDatabase.execSQL("delete from thread_info where url=?and thread_id=?", new Object[]{url,thread_id});
writableDatabase.close();
}
@Override
public void updateThreadInfo(String url, int thread_id,int finished) { SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
writableDatabase.execSQL("update thread_info set finished=? where url=?and thread_id=?", new Object[]{finished,url,thread_id});
writableDatabase.close();
} @Override
public List<ThreadInfo> getThreadInfo(String url) { SQLiteDatabase readableDatabase = dbHelper.getReadableDatabase();
List<ThreadInfo>list = new ArrayList<>(); Cursor cursor = readableDatabase.rawQuery("select * from thread_info where url=?",new String[]{url});
while (cursor.moveToNext()){
ThreadInfo thread =new ThreadInfo();
thread.setId(cursor.getInt(cursor.getColumnIndex("thread_id")));
thread.setUrl(cursor.getString(cursor.getColumnIndex("url")));
thread.setStart(cursor.getInt(cursor.getColumnIndex("start")));
thread.setEnd(cursor.getInt(cursor.getColumnIndex("end")));
thread.setFinished(cursor.getInt(cursor.getColumnIndex("finished")));
list.add(thread); } readableDatabase.close();
cursor.close();
return list;
}
@Override
public boolean findThreadInfo(String url, int thread_id) {
SQLiteDatabase readableDatabase = dbHelper.getReadableDatabase();
List<ThreadInfo>list = new ArrayList<>();
Cursor cursor = readableDatabase.rawQuery("select * from thread_info where url=? and thread_id=?",new String[]{url,thread_id+""});
boolean b = cursor.moveToNext();
readableDatabase.close();
cursor.close();
return b;
}
}
三、建立下载服务Service
package com.example.zjw.myapplication.service; import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log; import com.example.zjw.myapplication.dao.FileInfo;
import com.example.zjw.myapplication.dao.ThreadInfo; import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; /**
* 下载文件服务
*/
public class DownloadService extends Service { public static final String ACTION_START="ACTION_START";
public static final String ACTION_STOP="ACTION_STOP";
public static final int MSG_INIT=10;
public static final String UPDATE="UPDATE";
private DownloadTask task;
public static String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/MyDownload"; public DownloadService() {
} @Override
public int onStartCommand(Intent intent, int flags, int startId) { //获取activity传来的参数
if(ACTION_START.equals(intent.getAction())){
FileInfo fileInfo = (FileInfo)intent.getSerializableExtra("fileInfo");
Log.d("TAG-----", "onStartCommand: 开始下载"+fileInfo.toString());
new Thread(new InitThread(fileInfo)).start();
}
if(ACTION_STOP.equals(intent.getAction())){
Serializable fileInfo = (FileInfo)intent.getSerializableExtra("fileInfo");
Log.d("TAG-----", "onStartCommand: 暂停下载"+fileInfo);
if(task!=null){
task.isDownload=true;
}
}
return super.onStartCommand(intent, flags, startId);
} @Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
} private Handler handler =new Handler(){ @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){ case MSG_INIT:
FileInfo fileInfo = (FileInfo) msg.obj;
Log.d("TAG", "handleMessage:-------------> "+fileInfo); //启动下载任务
task = new DownloadTask(fileInfo,DownloadService.this);
task.download();
break;
}
}
};
/**
* 初始化子线程
*/ private class InitThread implements Runnable{ private FileInfo fileInfo;
private RandomAccessFile ws; public InitThread(FileInfo threadInfo){ this.fileInfo=threadInfo;
} @Override
public void run() {
HttpURLConnection conn=null;
try {
URL url =new URL(fileInfo.getUrl());
conn= (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.connect();
int length=-1;
if(conn.getResponseCode()==HttpURLConnection.HTTP_OK){
length=conn.getContentLength();//获取下载文件长度
} if(length<=0){
return;
}
//创建文件夹
File dir = new File(path);
if(!dir.exists()){
dir.mkdir();
}
File file = new File(dir,fileInfo.getName());
this.ws = new RandomAccessFile(file,"rwd");
ws.setLength(length);
fileInfo.setLength(length);
Message msg =new Message();
msg.obj=fileInfo;
msg.what=MSG_INIT;
handler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}finally {
conn.disconnect();
try {
if(ws!=null)
ws.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
四、建立下载任务类
package com.example.zjw.myapplication.service; import android.content.Context;
import android.content.Intent;
import android.util.Log; import com.example.zjw.myapplication.dao.FileInfo;
import com.example.zjw.myapplication.dao.ThreadInfo;
import com.example.zjw.myapplication.db.ThreadDao;
import com.example.zjw.myapplication.db.ThreadDaoImpl; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List; /**下载任务类
* Created by Administrator on 2016/6/20.
*/
public class DownloadTask { private FileInfo fileInfo=null;
private Context context;
private ThreadDao threadDao;
public boolean isDownload;
private int finished; public DownloadTask(FileInfo fileInfo, Context context) {
this.fileInfo = fileInfo;
this.context = context;
this.threadDao=new ThreadDaoImpl(context);
} //下载文件
public void download(){ //读取数据库线程信息
List<ThreadInfo> threadInfos = threadDao.getThreadInfo(fileInfo.getUrl());
ThreadInfo threadInfo =null;
if(threadInfos.size()==0){ threadInfo =new ThreadInfo(0,fileInfo.getUrl(),0,fileInfo.getLength(),0);
}else {
threadInfo=threadInfos.get(0);
Log.d("TAG----------", threadInfo.getEnd()+"---download: ---"+threadInfo.getFinished());
}
//创建子线程下载文件
new Thread(new DownloadThread(threadInfo)).start();
} //实现下载
private class DownloadThread implements Runnable{
private ThreadInfo threadInfo;
public DownloadThread(ThreadInfo threadInfo) {
this.threadInfo = threadInfo;
} @Override
public void run() {
//向数据库插入线程信息
if(!threadDao.findThreadInfo(threadInfo.getUrl(),threadInfo.getId())){
threadDao.addThreadInfo(threadInfo);
}
try {
URL url =new URL(threadInfo.getUrl());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5*1000);
//设置下载位置
int start=threadInfo.getStart()+threadInfo.getFinished();
conn.setRequestProperty("Range","bytes="+start+"-"+threadInfo.getEnd());
//设置文件写入位置
File file =new File(DownloadService.path,fileInfo.getName());
RandomAccessFile ws = new RandomAccessFile(file,"rwd");
ws.seek(start);
//开始下载
//注意别写成200了不然就无法完成断点下载,206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它(HTTP 1.1新)。
if(conn.getResponseCode()==206){ InputStream inputStream = conn.getInputStream();
byte[] data = new byte[1024];
int len=-1;
Intent intent=new Intent(DownloadService.UPDATE);
finished=threadInfo.getFinished(); //读取文件
while ((len=inputStream.read(data))!=-1){
//写入文件
ws.write(data,0,len);
//发送广播更新进度条
finished+=len; intent.putExtra("finished", finished * 100 / fileInfo.getLength());
context.sendBroadcast(intent);
Log.d("TAG----******-----", threadInfo.getEnd()+"---download: ---"+finished);
//下载暂停,保存下载进度
if(isDownload){ threadDao.updateThreadInfo(threadInfo.getUrl(),threadInfo.getId(),finished); return;
} } //删除线程信息
threadDao.deleteThreadInfo(threadInfo.getUrl(),threadInfo.getId());
ws.close();
inputStream.close();
conn.disconnect();
} } catch (Exception e) {
e.printStackTrace();
}
} } }
五、在acticity中调用
package com.example.zjw.myapplication; import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast; import com.example.zjw.myapplication.dao.FileInfo;
import com.example.zjw.myapplication.dao.ThreadInfo;
import com.example.zjw.myapplication.db.ThreadDaoImpl;
import com.example.zjw.myapplication.service.DownloadService; import java.util.List; public class DownloadActivity extends AppCompatActivity { private ProgressBar progressBar;
private TextView tv; private boolean isDownload; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
this.progressBar= (ProgressBar) this.findViewById(R.id.progressBar);
progressBar.setMax(100);
this.tv = (TextView) this.findViewById(R.id.progressTv); //开始下载
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { if(!isDownload){
FileInfo fileInfo =new FileInfo(0,"http://b.hiphotos.baidu.com/image/pic/item/0823dd54564e925838c205c89982d158ccbf4e26.jpg","110.jpg",0,0);
Intent intent = new Intent(DownloadActivity.this,DownloadService.class);
intent.setAction(DownloadService.ACTION_START);
intent.putExtra("fileInfo",fileInfo);
startService(intent);
isDownload=true;
}
}
});
//停止下载
findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// downloadFileUtil.setIsDownload(false);
isDownload=false;
FileInfo fileInfo =new FileInfo(0,"http://b.hiphotos.baidu.com/image/pic/item/0823dd54564e925838c205c89982d158ccbf4e26.jpg","112.jpg",0,0);
Intent intent = new Intent(DownloadActivity.this,DownloadService.class);
intent.setAction(DownloadService.ACTION_STOP);
intent.putExtra("fileInfo",fileInfo);
startService(intent);
}
}); init(); }
//初始化
private void init() { //当打开下载界面显示历史下载进度
ThreadDaoImpl dao =new ThreadDaoImpl(this);
List<ThreadInfo> threadInfos = dao.getThreadInfo("http://b.hiphotos.baidu.com/image/pic/item/0823dd54564e925838c205c89982d158ccbf4e26.jpg");
if(threadInfos.size()>0){
ThreadInfo threadInfo = threadInfos.get(0);
int value=threadInfo.getFinished()*100/threadInfo.getEnd();
progressBar.setProgress(value);
tv.setText(value+"%");
}
//注册广播
IntentFilter intent = new IntentFilter();
intent.addAction(DownloadService.UPDATE);
registerReceiver(reciver,intent);
} @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(reciver);
} BroadcastReceiver reciver =new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int finished = intent.getIntExtra("finished",-1);
if(finished!=-1){
if ( finished<=100) {
progressBar.setProgress( finished);
tv.setText( finished+"%");
if( finished==100){
isDownload=false;
Toast.makeText(DownloadActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
}
}
}
};
}
六、运行效果



安卓(android)之实现断点下载功能的更多相关文章
- Android之多线程断点下载
本文主要包含多线程下载的一些简单demo,包括三部分 java实现 android实现 XUtils开源库实现 注意下载添加网络权限与SD卡读写权限 java实现多线程下载 public class ...
- java 多线程断点下载功能
import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.Rand ...
- Java 断点下载(下载续传)服务端及客户端(Android)代码
原文: Java 断点下载(下载续传)服务端及客户端(Android)代码 - Stars-One的杂货小窝 最近在研究断点下载(下载续传)的功能,此功能需要服务端和客户端进行对接编写,本篇也是记录一 ...
- Android网络多线程断点续传下载
本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...
- andoid 多线程断点下载
本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...
- Java实现多线程断点下载(下载过程中可以暂停)
线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...
- iOS-服务器文件断点下载
文件下载基本步骤:1.获取下载链接,创建响应发送请求.(使用异步请求,避免因文件过大下载时间长而阻塞主线程).2.当接到响应时在下载目录中创建文件.创建文件使用NSFileHandle进行文件内部处理 ...
- Java---多线程断点下载
在上一章中我们实现了多线程下载功能,这里我们添加断点下载功能,防止下载过程中程序意外退出.具体代码如下: package com.jwzhangjie; /** * 说明: * 每一个线程下载的位置计 ...
- 实现android支持多线程断点续传下载器功能
多线程断点下载流程图: 多线程断点续传下载原理介绍: 在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度手机端下载数据时难免会出现无信号断线.电量不足等情况,所以需要断点续传功能根据下 ...
随机推荐
- XCode8目录整理后的几个警告消除,Missing file
Git目录没有及时更新导致 终端进入目录运行如下命令 git rm main.m git rm Info.plist git rm AppDelegate.h git rm AppDelegate.m ...
- Spring框架学习(二)
一.Spring IOC参数值注入 1.注入基本值 1.1)<value></value>元素可以通过字符串指定属性或构造参数的值.容器将字符串从java.lang.Strin ...
- WhatsApp的Erlang世界
rick 的两个ppt整理 下载:2012 2013 ,使用半年erlang后,重新看这两个ppt才发现更多值的学习的地方,从ppt中整理如下: - Prefer os:timestamp to e ...
- remove mysql
apt-get --purge remove mysql-server mysql-client mysql-common apt-get autoremove rm -rf /etc/mysql r ...
- CocoaPods报错:The dependency `AFNetworking ` is not used in any concrete target 解决办法
产生这个问题的原因是最新版本的CocoaPods把Podfile文件的书写格式改变了,官网推荐用如下格式书写: platform :ios, '8.0' use_frameworks! target ...
- WinForm 遍历用户控件里CheckBox
1.常用调用方法 public partial class UCRights : UserControl { private readonly int LOCATIONY; private DataT ...
- C语言中,头文件和源文件的关系(转)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...
- jquery中的ajax参数说明
本文只作为记录,方便以后查阅. 内容原地址:$.ajax( )方法详解及案例_JQuery_wodi0007的博客_程序员博客网 http://u.cxyblog.com/28/article-aid ...
- hbase1.2.4 伪分布式安装
注意:在安装hbase或者hadoop的时候,要注意hadoop和hbase的对应关系.如果版本不对应可能造成系统的不稳定和一些其他的问题.在hbase的lib目录下可以看到hadoop对应jar文件 ...
- Duilib源码分析(四)绘制管理器—CPaintManagerUI
接下来,分析uilib.h中的UIManager.h,在正式分析CPaintManagerUI前先了解前面的一些宏.结构: 枚举类型EVENTTYPE_UI:定义了UIManager.h中事件通告类型 ...