Android 断点续传基础之单线程下载

news2024/11/27 4:17:38

**遇到的问题:**在这因为返回值的问题烦躁了一下,有可能出现空指针的异常,已经提出成文章了

请参考http://blog.csdn.net/qq_27489007/article/details/53523378

文件关系图

断点续传流程图

开始撸代码(主要代码)

/**

  • 普通断点续传

*/

public class DuandianActivity extends AppCompatActivity {

@BindView(R.id.tv)

TextView tv;

@BindView(R.id.probar)

ProgressBar probar;

@BindView(R.id.btstar)

Button btstar;

@BindView(R.id.btstop)

Button btstop;

String url = “http://dldir1.qq.com/weixin/android/weixin6316android780.apk”;

private FileInfo fileInfo;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_duandian);

ButterKnife.bind(this);

probar.setMax(100);

//创建文件信息对象

fileInfo = new FileInfo(0, url, “文件名-下载进度”, 0, 0);

tv.setText(fileInfo.getFileName()); //设置显示下载的文件名

//注册广播接收器

IntentFilter filter = new IntentFilter();

filter.addAction(DownloadService.ACTION_UPDATE);

registerReceiver(mReceiver, filter);

}

//更新ui的广播接收器

BroadcastReceiver mReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

if (DownloadService.ACTION_UPDATE.equals(intent.getAction())) {

int finished = intent.getIntExtra(“finished”, 0);

probar.setProgress(finished);

if (probar.getProgress()==100){

Toast.makeText(DuandianActivity.this,“下载完成!”,Toast.LENGTH_SHORT).show();

}

}

}

};

//按钮事件监听

@OnClick({R.id.btstar, R.id.btstop})

public void onClick(View view) {

Intent intent = new Intent(DuandianActivity.this, DownloadService.class);

switch (view.getId()) {

case R.id.btstar:

//通过intent传递参数给service

intent.setAction(DownloadService.ACTION_START);

intent.putExtra(“fileInfo”, fileInfo);

Log.i(“TAG”,intent.getAction().toString());

startService(intent);

break;

case R.id.btstop:

intent.setAction(DownloadService.ACTION_STOP);

intent.putExtra(“fileInfo”, fileInfo);

startService(intent);

break;

}

}

@Override

protected void onDestroy() {

super.onDestroy();

if (mReceiver != null) {

unregisterReceiver(mReceiver);

}

}

}

DownloadService.java

/**

  • 下载的服务类

*/

public class DownloadService extends Service {

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 String DOWNLOAD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + “/download”;//sd卡路径

private DownloadTask mDownloadTask = null;

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

// Log.i(“TAG”, intent.getAction().toString());

// Log.i(“action”, intent.getAction().toString());

//获得activity传来的参数

if (ACTION_START.equals(intent.getAction())) {

FileInfo fileInfo = (FileInfo) intent.getSerializableExtra(“fileInfo”);

Log.i(“test”, “start” + fileInfo.toString());

//启动初始化线程

new InitThread(fileInfo).start();

} else if (ACTION_STOP.equals(intent.getAction())) {

FileInfo fileInfo = (FileInfo) intent.getSerializableExtra(“fileInfo”);

Log.i(“test”, “stop” + fileInfo.toString());

if (mDownloadTask != null) {

mDownloadTask.isPause = true;

Toast.makeText(getApplicationContext(),“暂停成功”,Toast.LENGTH_SHORT).show();

}else {

Toast.makeText(getApplicationContext(),“还未开始下载”,Toast.LENGTH_SHORT).show();

}

}

return super.onStartCommand(intent, Service.START_REDELIVER_INTENT, startId);

}

@Override

public IBinder onBind(Intent intent) {

return null;

}

private static final int MSG_INIT = 0;

Handler mhandler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

switch (msg.what) {

case MSG_INIT:

FileInfo fileInfo = (FileInfo) msg.obj;

Log.i(“test”, “Init:” + fileInfo);

//启动下载任务

mDownloadTask = new DownloadTask(DownloadService.this, fileInfo);

mDownloadTask.download();

break;

}

}

};

/**

  • 子线程进行下载保存工作

  • 初始化子线程

*/

class InitThread extends Thread {

private FileInfo thread_fileInfo = null;

private RandomAccessFile raf;

public InitThread(FileInfo fileInfo) {

this.thread_fileInfo = fileInfo;

}

@Override

public void run() {

//连接网络文件

HttpURLConnection conn = null;

try {

URL url = new URL(thread_fileInfo.getUrl());

conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod(“GET”
);

conn.setConnectTimeout(3000);

int length = -1;

if (conn.getResponseCode() == 200) {

//获得文件长度

length = conn.getContentLength();

}

if (length <= 0) {

return;

}

File dir = new File(DOWNLOAD_PATH);

if (!dir.exists()) { //判断如果不存在则创建一个文件

dir.mkdir();

}

//在本地创建文件

File file = new File(dir, thread_fileInfo.getFileName());

//随机访问的文件 可以在文件的任意一个位置进行写入操作

//rwd可读可写可操作

raf = new RandomAccessFile(file, “rwd”);

//设置文件长度

raf.setLength(length);

thread_fileInfo.setLength(length);

mhandler.obtainMessage(MSG_INIT, thread_fileInfo).sendToTarget();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

if (conn != null && raf != null) {

raf.close(); //关闭文件操作

conn.disconnect(); //断掉链接

}

} catch (IOException e) {

e.printStackTrace();

}

}

super.run();

}

}

}

DownloadTask.java

/**

  • 下载的任务类 对文件的下载

  • Created by lung on 2016-12-07.

*/

public class DownloadTask {

private Context mContext = null;

private FileInfo mFileInfo = null;

private ThreadDAOImpl mThreadDAO = null;

private long mFinished = 0; //总的完成进度

public boolean isPause = false; //暂停下载的开关

public DownloadTask(Context mContext, FileInfo mFileInfo) {

this.mContext = mContext;

this.mFileInfo = mFileInfo;

mThreadDAO = new ThreadDAOImpl(mContext);

}

//下载的方法

public void download() {

//读取数据库的线程信息

List threaddInfos = mThreadDAO.getThreads(mFileInfo.getUrl());

TheardInfo info;

if (threaddInfos.size() == 0) { //如果数据库无线程信息

info = new TheardInfo(0, mFileInfo.getUrl(), 0, mFileInfo.getLength(), 0);

} else {

info = threaddInfos.get(0);//单线程的下载 所以使用get(0)

}

//创建子线程进行下载

new DownloadThread(info).start();

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1834897.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FirstChip1179量产经历(附FirstChipMpTools_v20200430工具)

前言&#xff1a; 新工作的原因&#xff0c;需要频繁用到u盘&#xff0c;手头上有2个常用的U盘&#xff08;龙凤呈祥57.3G&#xff08;64G&#xff09;&#xff09; 一个用来存放课件ppt、word、excel等文件&#xff1b;一个用来存放一些软件工具&#xff1b; ps&#xff0c…

将Typora中图片从指定路径移动到当前文件夹下(准确位置为:XX.md文件所在目录/XX.assets/)

1、背景介绍 最开始时候,将复制到Typora中的图片放在了指定位置。但是在进行迁移(在别的电脑上打开md文件),会发现发送过来的文件不包含图片,导致文件内容缺失。解决办法就是将图片放在XX.md文件所在目录/XX.assets/。 2、方法 2.1 做好文件备份 2.2 替换图片链接中的…

又一个SQL Developer中调试存储过程的例子

此例基于OBE&#xff08;Oracle By Example&#xff09;的示例。是在SQL Developer中调试存储过程一文的进阶。复习了前文的一些基本概念&#xff0c;并纠正了官方示例的一个错误。 本文使用的是标准的HR 示例 Schema&#xff0c;调试的存储过程源代码如下&#xff1a; CREAT…

针对k8s集群已经加入集群的服务器进行驱逐

例如k8s 已经有很多服务器&#xff0c;现在由于服务器资源过剩&#xff0c;需要剥离一些服务器出来 查找节点名称&#xff1a; kubectl get nodes设置为不可调度&#xff1a; kubectl cordon k8s-node13恢复可调度 kubectl uncordon k8s-node13在驱逐之前先把需要剥离驱逐的节…

Vite+Vue3安装且自动按需引入Element Plus组件库

一&#xff0c;安装Element Plus npm install element-plus //node环境16二&#xff0c;安装插件 npm install unplugin-auto-import unplugin-vue-components -D三&#xff0c;配置vite.config.ts文件 //按需引入element-plus组件 import AutoImport from unplugin-auto-i…

电手出软件啦!各种姿势一键重装你的系统

电手的兄弟们你们好啊&#xff0c;很多兄弟都知道&#xff0c;我们老大傲梅是做软件的&#xff0c;例如大伙儿都用过的傲梅分区助手&#xff0c;还有傲梅轻松备份。相信不少兄弟都是用了分区助手才关注到电手的。 而我们电手&#xff0c;在电脑和手机玩机内容方面一直深耕。 跟…

9.2.2 DeepLab系列模型中每一代的创新是什么?是为了解决什么问题?

9.2.2 DeepLab系列模型中每一代的创新是什么&#xff1f;是为了解决什么问题&#xff1f; 前情回顾&#xff1a;9.2.1 简述图像分割中经常用到的编码器-解码器网络结构的设计理念。 DeepLab是Google 团队提出的一系列图像分割算法。 DeepLab v1在2014年被提出&#xff0c;并在…

SpringMVC系列十一: 文件上传与自定义拦截器

文章目录 SpringMVC文件上传基本介绍需求分析 / 图解应用实例-代码实现 自定义拦截器什么是拦截器自定义拦截器执行流程分析图自定义拦截器应用实例快速入门注意事项和细节Debug执行流程 多个拦截器多个拦截器执行流程示意图应用实例1代码实现注意事项和细节 应用实例2 作业布置…

汇编语言程序设计 - 新建一个文件:d:\abc.txt,从键盘输入文件的内容(不超过100个字符)

80x86汇编习题 题目描述&#xff1a;编写一个程序&#xff0c;新建一个文件&#xff1a;d:\abc.txt&#xff0c;从键盘输入文件的内容&#xff08;不超过100个字符&#xff09; 思路&#xff1a; 1&#xff0c;定义好文件名&#xff0c;记得末尾0 2&#xff0c;定义好缓冲区…

C#开发-集合使用和技巧(六)特殊转换方法SelectMany的介绍和用法

介绍 SelectMany 方法在C#中用于将集合中的元素转换为其他类型的集合&#xff0c;并将这些集合扁平化为一个单一的序列。它是LINQ的一部分&#xff0c;允许你在一个序列上进行投影和过滤操作&#xff0c;然后将结果合并成一个序列。 方法定义 public static IEnumerable<…

【Python机器学习实战】 | 基于决策树的药物研究分类预测

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

Python内置debug库: pdb用法详解

文章目录 0. 引言1. 基本用法1.1 设置断点1.2 通过命令行启动 pdb 2. 常用命令2.1 n (next)2.2 s (step)2.3 c (continue)2.4 l (list)2.5 p (print)2.6 h (help)2.7 b (break)2.8 cl (clear)2.9 q (quit) 3. 例子 0. 引言 pdb&#xff08;Python Debugger&#xff09;是Pytho…

【Redis】分布式锁基本理论与简单实现

目录 分布式锁解释作用特性实现方式MySQL、Redis、Zookeeper三种方式对比 原理 reids分布式锁原理目的容错redis简单分布式锁实现锁接口实现类下单场景的实现容错场景1解决思路优化代码 容错场景2Lua脚本Redis利用Lua脚本解决多条命令原子性问题 释放锁的业务流程Lua脚本来表示…

SpringMVC系列九: 数据格式化与验证及国际化

SpringMVC 数据格式化基本介绍基本数据类型和字符串自动转换应用实例-页面演示方式Postman完成测试 特殊数据类型和字符串自动转换应用实例-页面演示方式Postman完成测试 验证及国际化概述应用实例代码实现注意事项和使用细节 注解的结合使用先看一个问题解决问题 数据类型转换…

游泳耳机哪个牌子好性价比高?精选高性价比的四大游泳耳机!

在现代社会中&#xff0c;随着健身和水中运动的普及&#xff0c;游泳耳机作为一种关键的健身配件&#xff0c;正日益受到广泛关注和需求。无论是在游泳池畅游还是深潜海底&#xff0c;好的游泳耳机不仅能提供高品质的音乐享受&#xff0c;更能保护耳朵免受水压和湿润环境的侵害…

训练营第四十一天| 1035.不相交的线53. 最大子序和392.判断子序列115.不同的子序列

1035.不相交的线 力扣题目链接(opens new window) 我们在两条独立的水平线上按给定的顺序写下 A 和 B 中的整数。 现在&#xff0c;我们可以绘制一些连接两个数字 A[i] 和 B[j] 的直线&#xff0c;只要 A[i] B[j]&#xff0c;且我们绘制的直线不与任何其他连线&#xff08;…

线上扭蛋机小程序开发,潮玩时代的创新发展

随着互联网的发展&#xff0c;扭蛋机市场也进行了创新发展&#xff0c;线上扭蛋机小程序为市场带来了新活力。扭蛋机小程序将传统的模式与互联网结合&#xff0c;打造一个便捷有趣的扭蛋机市场。 一、扭蛋机小程序 在扭蛋机小程序上&#xff0c;用户通过扭蛋机抽取各种系列的…

实现锚点链接点击tab跳转到指定位置 并且滚动鼠标顶部锚点的样式也跟随变化

实现效果如下 不管是点击还是 滚动鼠标 顶部的样式也会跟随变化 点击会跳转到指定的位置 通过IntersectionObserver 监听是否可见 下面代码可以直接执行到vue的文件 <template><div><ul class"nav"><li v-for"tab in tabs" :key…

【Java】已解决Spring框架中的org.springframework.dao.DuplicateKeyException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决Spring框架中的org.springframework.dao.DuplicateKeyException异常 一、问题背景 在使用Spring框架进行数据库操作时&#xff0c;有时会遇到org.springframework.dao.Duplicate…

HTML 全局属性介绍及示例

HTML 全局属性是一组可以在任何HTML元素中使用的属性。这些属性提供了一种方式来定义元素的通用行为或外观。以下是一些常见的HTML全局属性及其示例。 id id 属性为元素提供了一个唯一的标识符。它不能在 <head>, <html>, <meta>, <script>, <sty…