Android 根据Url使用Retrofit框架进行文件下载

一、背景

根据后端返回的url下载地址,去执行文件下载,将文件保存到SD卡。这里使用Retrofit网络框架。

二、代码实现

2.1、定义一个DownloadFileService
interface DownloadFileService {@Streaming@GETsuspend fun downloadFile(@Url fileUrl: String):ResponseBody
}
2.2、定义一个FileDownloadClient
private var mDownliadService: DownloadFileService? = nullfun getUploadFileService() :DownloadFileService{if(mDownliadService==null){val okHttpClient = OkHttpClient.Builder().callTimeout(0, TimeUnit.SECONDS)//0 代表不考虑请求的超时 这里的超时是指整个请求过程的超时,如果设置太短,任务还没执行完,会以超时结束任务,这里尤其要注意.connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).retryOnConnectionFailure(false)// 重连.followRedirects(false)// 重定向//.addInterceptor(RequestInterceptor(authorization,requestId,offset,uploadType))//.addInterceptor(RemoveContentLengthInterceptor())//.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build()val retrofit: Retrofit = Retrofit.Builder().baseUrl(DeviceUtil.getInstance().getServerIp()).addConverterFactory(GsonConverterFactory.create()).client(okHttpClient).build()mDownliadService= retrofit.create(DownloadFileService::class.java)}return mDownliadService!!}
2.3、定义一个DownloadCallback
interface DownloadCallback {fun onSuccess(srcApkTarPath:String)fun onProgress(progress: Int)fun onFailure(msg:String?)
}
2.4、定义一个FileDownloadManager,执行文件下载
class FileDownloadManager {private val TAG = "FileDownloadManager_"companion object {private var singleInstance: FileDownloadManager? = nullget() {// 懒汉模式if (null == field) {field = FileDownloadManager()}return field}@Synchronized // 添加注解,线程同步,线程安全fun getInstance(): FileDownloadManager {return singleInstance!! // 表示非空时执行}}fun doDownloadFile(appName:String,packageName: String,downUrl: String,fileSize: Long,fileMd5:String,downloadCallback: DownloadCallback) {try {val coroutineScope = CoroutineScope(Dispatchers.Default)coroutineScope.launch(Dispatchers.IO) {val response = FileDownloadClient.getUploadFileService().downloadFile(downUrl)val length = response.contentLength()XLogUtil.d("${TAG}doDownloadFile result appName:$appName,,,packageName:$packageName,,,length:$length,,,fileSize:$fileSize,,,downUrl:$downUrl")if (length > 0) {val folder = File(ConstantUtil.DOWNLOAD_FOLDER_PATH)if (!folder.exists()) {folder.mkdirs()}// 使用输入流保存响应体到文件val inputStream = response.byteStream()val fileName = "$packageName.tar"var fileTargetPath =ConstantUtil.DOWNLOAD_FOLDER_PATH + File.separator + fileNameval outputStream = FileOutputStream(fileTargetPath)val buf = ByteArray(1024)var downLoadFileSize = 0var lastProgress = 0do {val numread = inputStream.read(buf)if (numread == -1) {break}outputStream.write(buf, 0, numread)downLoadFileSize += numreadval progressValue =((downLoadFileSize * 100f) / length).toInt()//相同的进度值只回调一次if (progressValue > lastProgress) {lastProgress = progressValuedownloadCallback?.apply {onProgress(progressValue)}}} while (true)outputStream.flush()// 关闭文件输出流和输入流outputStream.close()//inputStream.close()val localFileMd5=FileUtil.getInstance().getFileMd5(fileTargetPath)if(localFileMd5==fileMd5){downloadCallback?.onSuccess(fileTargetPath)}else{downloadCallback?.onFailure("文件 md5 不一致,localFileMd5:$localFileMd5,,,fileMd5:$fileMd5")}}else{downloadCallback?.onFailure("读取文件len=0")}}} catch (e: Exception) {XLogUtil.e("${TAG}doDownloadFile Exception appName:$appName,,,packageName:$packageName,,,Exception:${e.message},,,fileSize:$fileSize,,,downUrl:$downUrl")downloadCallback?.onFailure(e.message)}}
}

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

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

相关文章

NVMe(Non-Volatile Memory Express)详解

一、NVMe的定义与核心特性 NVMe(非易失性内存主机控制器接口规范)是一种 基于PCIe总线的高性能存储协议,专为固态硬盘(SSD)设计,旨在替代传统的AHCI协议(如SATA)。其核心特性包括&a…

机器学习——KNN超参数

sklearn.model_selection.GridSearchCV 是 scikit-learn 中用于超参数调优的核心工具,通过结合交叉验证和网格搜索实现模型参数的自动化优化。以下是详细介绍: 一、功能概述 GridSearchCV 在指定参数网格上穷举所有可能的超参数组合,通过交叉…

稳定运行的以Oracle NoSQL数据库为数据源和目标的ETL性能变差时提高性能方法和步骤

提高基于Oracle NoSQL数据库的ETL(提取、转换、加载)性能时,主要从多个角度进行优化。 提高基于Oracle NoSQL数据库的ETL性能需要综合考虑多个方面,关键是减少不必要的I/O操作、优化数据转换和加载过程、合理配置Oracle NoSQL数据…

Compose 原理解析

Compose 的组件都是放在 setContent() 之后才能显示的,那需要先看看这个函数的作用。 先看 ComponentActivity 的扩展函数 setContent(): /*** 将给定的可组合项合成到给定的 Activity 中。[content] 将成为给定 Activity 的根视图。* 这大致相当于使用…

细说卫星导航:测距定位原理

测距定位原理 1. 伪距测量技术 核心原理:卫星发射信号,用户接收并记录传播时间,乘以光速得到距离(伪距)。 技术细节: 信号传播路径分析 信号结构: 卫星信号包含三部分: 载波&…

19921 多重背包

19921 多重背包 ⭐️难度:中等 🌟考点:动态规划、背包问题 📖 📚 import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N …

js逆向之断点调试

1.XHR/提取断点用法 当刷新页面时候,有大量请求,并且你无法定位参数信息的时候,或者参数被混淆无法搜到,可以用该方法,该方法是会捕获所有请求连接,然后我们通过连接过滤出自己想要的请求,然后…

基于32单片机的无人机直流电机闭环调速系统设计

标题:基于32单片机的无人机直流电机闭环调速系统设计 内容:1.摘要 本文针对无人机直流电机调速需求,设计了基于32单片机的无人机直流电机闭环调速系统。背景在于无人机应用场景不断拓展,对电机调速精度和稳定性要求日益提高。目的是开发一套高精度、响应…

如何用Deepseek制作流程图?

使用Deepseek制作流程图,本质上是让AI根据你的需求,生成相关流程图的代码,然后在流程图编辑器中渲染,类似于Python一样,ChatGPT可以生成代码,但仍需在IDE中执行。 你知道绘制流程图最高效的工具是什么吗&a…

嵌入式硬件工程师从小白到入门-原理图(三)

原理图绘制从小白到入门:知识点速通与注意事项 一、原理图绘制基础概念 什么是原理图? 原理图(Schematic)是电子电路的图形化表示,展示元器件之间的电气连接关系,是硬件设计的蓝图。 核心元素 元器件符号&…

WSL 环境桥接与雷达通信配置笔记

作者: DWDROME 维护时间: 2025-03-22 参考文章:Windows子系统(WSL)通过桥接网络实现被外部局域网主机直接访问 WSL 环境桥接与雷达通信配置笔记 环境说明 Windows 11 专业版(启用 Hyper-V)WSL2 Ubuntu 20.04物理网线&#xff08…

ToDesk云电脑各类鼠标有什么区别?虚拟/3D/游戏鼠标等各有利

不知道各位在使用ToDesk云电脑的时候是否是有注意到,这其中的鼠标竟有多种名称、多种模式可以选,比如锁定鼠标、3D鼠标、游戏鼠标这几项。 那么这些不同名称的鼠标都代表什么意思呐,又应该怎么选择、怎么用呐?本篇内容小编就为大…

DeepBI:重构流量逻辑,助力亚马逊广告实现高效流量增长

在日益激烈的跨境电商竞争环境中,广告投放早已从“粗放撒网”走向“精细化运营”。尤其是在亚马逊这样一个成熟且竞争白热化的平台,如何在广告预算有限的前提下实现高效曝光、精准触达、稳定转化,成为众多卖家和运营团队面临的核心挑战。 De…

java项目之基于ssm的毕业论文管理系统(源码+文档)

项目简介 毕业论文管理系统实现了以下功能: 本毕业论文管理系统主要实现的功能模块包括学生模块、导师模块和管理员模块三大部分,具体功能分析如下: (1)导师功能模块:导师注册登录后主要功能模块包括个人…

【自学笔记】Linux基础知识点总览-持续更新

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Linux 基础知识点总览目录Linux 简介文件和目录结构常用命令文件操作目录操作权限管理文本处理 Shell 脚本基础进程管理用户和组管理网络配置 总结 Linux 基础知识点…

【PCB工艺】晶体管的发展历史

晶体管被认为是20世纪最伟大的发明之一,因为没有晶体管就不会有现代电脑、手机或平板​​,你也无法阅读到这里的内容,因为不存在网络。 ——本文纯粹出于对过往奋斗在这个领域中科学家的缅怀。科学家有太多宝贵的思想和经验值得我们认真总结和…

第23章:Kubernetes网络模型深度剖析

第23章:Kubernetes网络模型深度剖析 作者:DogDog_Shuai 阅读时间:约25分钟 难度:高级 目录 1. 引言2. Kubernetes网络模型基础3. 四种网络通信模式4. CNI架构深度解析5. 网络实现原理

HTML应用指南:利用GET请求获取猫眼电影日票房信息——以哪吒2为例

2025年春节档期,国产动画电影《哪吒之魔童闹海》(以下简称《哪吒2》)以颠覆性的叙事风格与工业化制作水准震撼登场,不仅刷新了中国动画电影的票房纪录,更成为全球影史现象级作品。影片凭借春节档期的爆发式开局、持续5…

Model Context Protocol:下一代AI系统集成范式革命

在2023年全球AI工程化报告中,开发者面临的核心痛点排名前三的分别是:模型与业务系统集成复杂度(58%)、上下文管理碎片化(42%)、工具调用标准化缺失(37%)。传统API集成模式在对接大语言模型时暴露明显短板:RESTful接口无法承载动态上下文,GraphQL缺乏工具编排能力,gR…

Java 锁机制全面解析

在 Java 并发编程中,锁(Lock)是保证线程安全的关键工具。本文将全面介绍 Java 的锁机制,包括 synchronized 关键字、Lock 接口及其实现、读写锁、乐观锁与悲观锁等,帮助新手理解 Java 并发控制。 1. Java 中的锁概述 …