Greendao+多线程断点续传

2024-04-25 06:18

本文主要是介绍Greendao+多线程断点续传,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

客官不要着急,下面给出你的困扰。想要用greendao首先需要配置

1、在app的Gradle中配置:

apply plugin'org.greenrobot.greendao'
dependencies {
        compile 'org.greenrobot:greendao:3.2.0'

}

2、在project的Gradle中配置:

dependencies {         classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'     } }
3.在app的Gradle(android)配置数据库版本等信息

greendao {
schemaVersion 1
daoPackage 'com.bwie.test.greendaodemo.gen'
targetGenDir 'src/main/java'
}
schemaVersion       对应当前数据库版本

daoPackage  GreenDao自动生成代码所在的包名,默认的是在项目包下面新建一个gen

targetGenDir    设置自动生成代码的目录

权限也粘一下的啦

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

因为grenndao的独特性,自动生成三个类,下面只给出实体类以及需要的操作


一点也不吝啬,别着急,实体类在这呢,记得生成实体类之后在buils下make project一下,让他自动生成三大类

@Entitypublic class User {@Idprivate Long id;private Integer thread_id;private Integer start_pos;private Integer end_pos;private Integer compelete_size;private String url;@Generated(hash = 2041931179)public User(Long id, Integer thread_id, Integer start_pos, Integer end_pos,Integer compelete_size, String url) {this.id = id;this.thread_id = thread_id;this.start_pos = start_pos;this.end_pos = end_pos;this.compelete_size = compelete_size;this.url = url;}@Generated(hash = 586692638)public User() {}public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public Integer getThread_id() {return this.thread_id;}public void setThread_id(Integer thread_id) {this.thread_id = thread_id;}public Integer getStart_pos() {return this.start_pos;}public void setStart_pos(Integer start_pos) {this.start_pos = start_pos;}public Integer getEnd_pos() {return this.end_pos;}public void setEnd_pos(Integer end_pos) {this.end_pos = end_pos;}public Integer getCompelete_size() {return this.compelete_size;}public void setCompelete_size(Integer compelete_size) {this.compelete_size = compelete_size;}public String getUrl() {return this.url;}public void setUrl(String url) {this.url = url;}}

好人做到低,下面附上需要的单例模式,因为本人用的是单例模式,用来数据库的初始化,并且获得操作类

public class App extends Application {public static UserDao userDao;@Overridepublic void onCreate() {super.onCreate();DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "lenvess.db", null);DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());DaoSession daoSession = daoMaster.newSession();userDao = daoSession.getUserDao();}
}


第一个类,主要是记录的类,修改,添加和最后下载完清空数据库的类

public class DownlaodSqlTool {/*** 创建下载的具体信息*/public void insertInfos(List<DownloadInfo> infos) {for (DownloadInfo info : infos) {User user = new User(null, info.getThreadId(), info.getStartPos(), info.getEndPos(), info.getCompeleteSize(), info.getUrl());userDao.insert(user);}}/*** 得到下载具体信息*/public List<DownloadInfo> getInfos(String urlstr) {List<DownloadInfo> list = new ArrayList<DownloadInfo>();List<User> list1 = userDao.queryBuilder().where(UserDao.Properties.Url.eq(urlstr)).build().list();for (User user : list1) {DownloadInfo infoss = new DownloadInfo(user.getThread_id(), user.getStart_pos(), user.getEnd_pos(),user.getCompelete_size(), user.getUrl());Log.d("main-----", infoss.toString());list.add(infoss);}return list;}/*** 更新数据库中的下载信息*/public void updataInfos(int threadId, int compeleteSize, String urlstr) {User user = userDao.queryBuilder().where(UserDao.Properties.Thread_id.eq(threadId), UserDao.Properties.Url.eq(urlstr)).build().unique();user.setCompelete_size(compeleteSize);userDao.update(user);}/*** 下载完成后删除数据库中的数据*/public void delete(String url) {userDao.deleteAll();}}
2.多线程下载的实践类
public class DownloadHttpTool {/*** 利用Http协议进行多线程下载具体实践类*/private static final String TAG = DownloadHttpTool.class.getSimpleName();private int threadCount;//线程数量private String urlstr;//URL地址private Context mContext;private Handler mHandler;private List<DownloadInfo> downloadInfos;//保存下载信息的类private String localPath;//目录private String fileName;//文件名private int fileSize;private DownlaodSqlTool sqlTool;//文件信息保存的数据库操作类private enum Download_State {Downloading, Pause, Ready;//利用枚举表示下载的三种状态}private Download_State state = Download_State.Ready;//当前下载状态private int globalCompelete = 0;//所有线程下载的总数public DownloadHttpTool(int threadCount, String urlString,String localPath, String fileName, Context context, Handler handler) {super();this.threadCount = threadCount;this.urlstr = urlString;this.localPath = localPath;this.mContext = context;this.mHandler = handler;this.fileName = fileName;sqlTool = new DownlaodSqlTool();}//在开始下载之前需要调用ready方法进行配置public void ready() {Log.w(TAG, "ready");globalCompelete = 0;downloadInfos = sqlTool.getInfos(urlstr);if (downloadInfos.size() == 0) {initFirst();} else {File file = new File(localPath + "/" + fileName);if (!file.exists()) {sqlTool.delete(urlstr);initFirst();} else {fileSize = downloadInfos.get(downloadInfos.size() - 1).getEndPos();for (DownloadInfo info : downloadInfos) {globalCompelete += info.getCompeleteSize();}Log.w(TAG, "globalCompelete:::" + globalCompelete);}}}public void start() {Log.w(TAG, "start");if (downloadInfos != null) {if (state == Download_State.Downloading) {return;}state = Download_State.Downloading;for (DownloadInfo info : downloadInfos) {Log.v(TAG, "startThread");new DownloadThread(info.getThreadId(), info.getStartPos(),info.getEndPos(), info.getCompeleteSize(),info.getUrl()).start();}}}public void pause() {state = Download_State.Pause;}public void delete() {compelete();File file = new File(localPath + "/" + fileName);file.delete();}public void compelete() {sqlTool.delete(urlstr);}public int getFileSize() {return fileSize;}public int getCompeleteSize() {return globalCompelete;}//第一次下载初始化private void initFirst() {Log.w(TAG, "initFirst");try {URL url = new URL(urlstr);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(5000);connection.setRequestMethod("GET");fileSize = connection.getContentLength();Log.w(TAG, "fileSize::" + fileSize);File fileParent = new File(localPath);if (!fileParent.exists()) {fileParent.mkdir();}File file = new File(fileParent, fileName);if (!file.exists()) {file.createNewFile();}// 本地访问文件RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");accessFile.setLength(fileSize);accessFile.close();connection.disconnect();} catch (Exception e) {e.printStackTrace();}int range = fileSize / threadCount;downloadInfos = new ArrayList<DownloadInfo>();for (int i = 0; i < threadCount - 1; i++) {DownloadInfo info = new DownloadInfo(i, i * range, (i + 1) * range- 1, 0, urlstr);downloadInfos.add(info);}DownloadInfo info = new DownloadInfo(threadCount - 1, (threadCount - 1)* range, fileSize - 1, 0, urlstr);downloadInfos.add(info);sqlTool.insertInfos(downloadInfos);}//自定义下载线程private class DownloadThread extends Thread {private int threadId;private int startPos;private int endPos;private int compeleteSize;private String urlstr;private int totalThreadSize;public DownloadThread(int threadId, int startPos, int endPos,int compeleteSize, String urlstr) {this.threadId = threadId;this.startPos = startPos;this.endPos = endPos;totalThreadSize = endPos - startPos + 1;this.urlstr = urlstr;this.compeleteSize = compeleteSize;}@Overridepublic void run() {HttpURLConnection connection = null;RandomAccessFile randomAccessFile = null;InputStream is = null;try {randomAccessFile = new RandomAccessFile(localPath + "/"+ fileName, "rwd");randomAccessFile.seek(startPos + compeleteSize);URL url = new URL(urlstr);connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(5000);connection.setRequestMethod("GET");connection.setRequestProperty("Range", "bytes="+ (startPos + compeleteSize) + "-" + endPos);is = connection.getInputStream();byte[] buffer = new byte[1024];int length = -1;while ((length = is.read(buffer)) != -1) {randomAccessFile.write(buffer, 0, length);compeleteSize += length;Message message = Message.obtain();message.what = threadId;message.obj = urlstr;message.arg1 = length;mHandler.sendMessage(message);sqlTool.updataInfos(threadId, compeleteSize, urlstr);Log.w(TAG, "Threadid::" + threadId + "    compelete::"+ compeleteSize + "    total::" + totalThreadSize);if (compeleteSize >= totalThreadSize) {break;}if (state != Download_State.Downloading) {break;}}} catch (Exception e) {e.printStackTrace();} finally {try {if (is != null) {is.close();}randomAccessFile.close();connection.disconnect();} catch (Exception e) {e.printStackTrace();}}}}
}
3.保存每个下载线程下载信息的类
public class DownloadInfo {
/**
     * 保存每个下载线程下载信息类**/private int threadId;// 下载器idprivate int startPos;// 开始点private int endPos;// 结束点private int compeleteSize;// 完成度private String url;// 下载文件的URL地址public DownloadInfo(int threadId, int startPos, int endPos,int compeleteSize, String url) {this.threadId = threadId;this.startPos = startPos;this.endPos = endPos;this.compeleteSize = compeleteSize;this.url = url;}public DownloadInfo() {}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public int getThreadId() {return threadId;}public void setThreadId(int threadId) {this.threadId = threadId;}public int getStartPos() {return startPos;}public void setStartPos(int startPos) {this.startPos = startPos;}public int getEndPos() {return endPos;}public void setEndPos(int endPos) {this.endPos = endPos;}public int getCompeleteSize() {return compeleteSize;}public void setCompeleteSize(int compeleteSize) {this.compeleteSize = compeleteSize;}@Overridepublic String toString() {return "DownloadInfo [threadId=" + threadId + ", startPos=" + startPos+ ", endPos=" + endPos + ", compeleteSize=" + compeleteSize+ "]";}}

4.这是一个接口类
public class DownloadUtil {private DownloadHttpTool mDownloadHttpTool;private OnDownloadListener onDownloadListener;private int fileSize;private int downloadedSize = 0;@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);int length = msg.arg1;synchronized (this) {//加锁保证已下载的正确性downloadedSize += length;}if (onDownloadListener != null) {onDownloadListener.downloadProgress(downloadedSize);}if (downloadedSize >= fileSize) {mDownloadHttpTool.compelete();if (onDownloadListener != null) {onDownloadListener.downloadEnd();}}}};public DownloadUtil(int threadCount, String filePath, String filename,String urlString, Context context) {mDownloadHttpTool = new DownloadHttpTool(threadCount, urlString,filePath, filename, context, mHandler);}//下载之前首先异步线程调用ready方法获得文件大小信息,之后调用开始方法public void start() {new AsyncTask<Void,Void,Void>() {@Overrideprotected Void doInBackground(Void... arg0) {// TODO Auto-generated method stubmDownloadHttpTool.ready();return null;}@Overrideprotected void onPostExecute(Void result) {// TODO Auto-generated method stubsuper.onPostExecute(result);fileSize = mDownloadHttpTool.getFileSize();downloadedSize = mDownloadHttpTool.getCompeleteSize();Log.w("Tag", "downloadedSize::" + downloadedSize);if (onDownloadListener != null) {onDownloadListener.downloadStart(fileSize);}mDownloadHttpTool.start();}}.execute();}public void pause() {mDownloadHttpTool.pause();}public void delete(){mDownloadHttpTool.delete();}public void reset(){mDownloadHttpTool.delete();start();}public void setOnDownloadListener(OnDownloadListener onDownloadListener) {this.onDownloadListener = onDownloadListener;}//下载回调接口public interface OnDownloadListener {public void downloadStart(int fileSize);public void downloadProgress(int downloadedSize);//记录当前所有线程下总和public void downloadEnd();}}


5.主的activity的类
public class MainActivity extends AppCompatActivity {private static final String TAG = MainActivity.class.getSimpleName();private ProgressBar mProgressBar;private Button start;private Button pause;private TextView total;private int max;private DownloadUtil mDownloadUtil;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);total= (TextView) findViewById(R.id.textView);start= (Button) findViewById(R.id.start);pause= (Button) findViewById(R.id.delete);mProgressBar= (ProgressBar) findViewById(R.id.progressBar);String urlString = "http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4";String localPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/local";mDownloadUtil = new DownloadUtil(2, localPath, "adc.mp4", urlString,this);mDownloadUtil.setOnDownloadListener(new DownloadUtil.OnDownloadListener() {@Overridepublic void downloadStart(int fileSize) {// TODO Auto-generated method stubLog.w(TAG, "fileSize::" + fileSize);max = fileSize;mProgressBar.setMax(fileSize);}@Overridepublic void downloadProgress(int downloadedSize) {// TODO Auto-generated method stubLog.w(TAG, "Compelete::" + downloadedSize);mProgressBar.setProgress(downloadedSize);total.setText((int) downloadedSize * 100 / max + "%");}@Overridepublic void downloadEnd() {// TODO Auto-generated method stubLog.w(TAG, "ENd");}});start.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubmDownloadUtil.start();}});pause.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubmDownloadUtil.pause();}});}



好了,布局也给你们了

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentStart="true"android:layout_alignParentTop="true"android:layout_marginLeft="23dp"android:layout_marginStart="23dp"android:layout_marginTop="18dp"android:text="TextView" /><ProgressBarandroid:id="@+id/progressBar"style="?android:attr/progressBarStyleHorizontal"android:layout_width="fill_parent"android:layout_height="7.5dp"android:layout_below="@+id/textView"android:layout_marginRight="8dp"android:max="100"android:progress="100"android:visibility="visible" /><Buttonandroid:id="@+id/start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_toEndOf="@+id/textView"android:layout_toRightOf="@+id/textView"android:text="下载" /><Buttonandroid:id="@+id/delete"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_marginLeft="48dp"android:layout_marginStart="48dp"android:layout_toEndOf="@+id/start"android:layout_toRightOf="@+id/start"android:text="暂停" /></RelativeLayout>

最后,客官们注意了,这里面的下载路径是local,自己更改喽。粘的难免出错,下面是Githb地址

GitHub  

效果图,布局可以更改

这篇关于Greendao+多线程断点续传的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933890

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

Qt中实现多线程导出数据功能的四种方式小结

《Qt中实现多线程导出数据功能的四种方式小结》在以往的项目开发中,在很多地方用到了多线程,本文将记录下在Qt开发中用到的多线程技术实现方法,以导出指定范围的数字到txt文件为例,展示多线程不同的实现方... 目录前言导出文件的示例工具类QThreadQObject的moveToThread方法实现多线程QC

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、

Python多进程、多线程、协程典型示例解析(最新推荐)

《Python多进程、多线程、协程典型示例解析(最新推荐)》:本文主要介绍Python多进程、多线程、协程典型示例解析(最新推荐),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 目录一、multiprocessing(多进程)1. 模块简介2. 案例详解:并行计算平方和3. 实现逻