安卓(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支持多线程断点续传下载器功能
多线程断点下载流程图: 多线程断点续传下载原理介绍: 在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度手机端下载数据时难免会出现无信号断线.电量不足等情况,所以需要断点续传功能根据下 ...
随机推荐
- Angular2 依赖注入
1. 使用DI 依赖注入是一个很重要的程序设计模式. Angular 有自己的依赖注入框架,离开了它,我们几乎没法构建 Angular 应用.它使用得非常广泛,以至于几乎每个人都会把它简称为 DI. ...
- 2015 史考特(Scottrade)开户指南 + 招商银行香港一卡通汇款【图文教程】
最近刚开始炒美股.总的来说分为两步:一是开户,即选一个美股券商开设股票交易账户:二是汇款注资,把人民币换成美元转账到股票交易账户上.上述第一点其实相对简单,美股券商大多都对美国以外的外国人开放申请,且 ...
- c#和js互通的AES加密解密
一.使用场景 在使用前后端分离的框架中常常会进行传输数据相互加密解密以确保数据的安全性,如web Api返回加密数据客户端或web端进行解密,或者客户端或web端进行加密提交数据服务端解密数据等等. ...
- Express的搭建--nodejs的学习
1,需要的学习环境 Node.js: 0.10.32 Express: 4.10.2 MongoDB: 2.6.1 2,安装Express $ npm install -g express-gener ...
- jquery动态添加的html,第三方插件无法生效的情况
今天一个问题纠结了半天,问题如下图 问题大致就是如上,新增的内容死活点不起,插件没有生效,在一个装逼前端群里面问,给我的答案是叫我去了解事件委托,了解一下事件冒泡!! 好吧,我一上午加半个下午的时间 ...
- SQL 检查 是否存在 表 临时表
1.检查临时表是否存在 已有临时表#temp2 if exists(select * from tempdb..sysobjects where id =object_id('tempdb..#tem ...
- glassfish配置
最近刚接触glassfish,在此记录一些glassfish的使用. 1.下载完glassfish之后(在配置玩JAVA路径后),解压缩.找到glassfish目录下的bin文件夹,运行asadmin ...
- 基于Netty与RabbitMQ的消息服务
Netty作为一个高性能的异步网络开发框架,可以作为各种服务的开发框架. 前段时间的一个项目涉及到硬件设备实时数据的采集,采用Netty作为采集服务的实现框架,同时使用RabbitMQ作为采集服务和各 ...
- C#设置IE代理及遇到问题的解决方案
起初使用的方法是修改完一次代理之后就不能继续修改,需要重新启动一次进程才可以,最初代码是: private void ShowProxyInfo() { if (!GetProxyStatus()) ...
- webform文件上传、图片水印、验证码
文件上传: 所用控件:FileUpload 使用时的思路: 1.判断用户是否选中了文件 FileUpload.FileName获取选中的文件名,判断长度,如果长度大于零就代表已经选择了文件 JS端:通 ...