// service write
interface UrlService {
@Streaming
@GET
suspend fun downloadFile(@Url url:String): Response<ResponseBody>
}
/ / Open the level of the assistance and download, in order to easily call, download the method I encapsulate into DSL, refer to DowloadBuild
lifecycleScope.launch() {
val response = RetrofitUtils.create()
.downloadfile ("File Download Address")
dowload(response){
success { uri ->
// Download success URI: Download file URI
// URI to File, you can refer to: https://blog.csdn.net/jingzz1/Article/details/106188462
}
error {throwable ->
//download failed
}
process { downloadedSize, length, process ->
// Download progress
// DownloadedSize: Downloaded Size
// Length: Document size
// process: Download progress
}
/ / Set the file name, if not set, will be automatically obtained
// setFileName = {"xxxxx. suffix"}
/ / In order to be compatible with Android10, if you need to download the file to the shared folder, you can call seruri.
/* setUri = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val values = ContentValues().apply {
PUT (MediaStore.Mediacolumns.Display_name, "xxxx.apk") // file name
Put (MediaStore.Mediacolumns.mime_type, response.body () ?. contenttype (). TOSTRING ()) // File Type
PUT (MediaStore.Mediacolumns.Rlative_path, Environment.directory_downloads) // Shared folder, fixed writing
}
context.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
} else
Uri.fromFile(File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.absolutePath+File.separator+"xxxxx.apk"))
}*/
} .startdowload () // call .Startdowload () Open Download
}
DowloadBuild code:
import android.content.Context
import android.net.Uri
import android.os.Environment
import android.webkit.MimeTypeMap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import retrofit2.Response
import java.io.BufferedInputStream
import java.io.File
import java.io.FileOutputStream
/**
* Created by jingzz on 2020/7/9.
*/
typealias DOWLOAD_ERROR = (Throwable) -> Unit
typealias DOWLOAD_PROCESS = (downloadedSize: Long, length: Long, process: Float) -> Unit
typealias DOWLOAD_SUCCESS = (uri: Uri) -> Unit
suspend fun dowload(response: Response<ResponseBody>,block:DowloadBuild.()->Unit):DowloadBuild{
val build = DowloadBuild(response)
build.block()
return build
}
class DowloadBuild(val response: Response<ResponseBody>) {
Private var error: download_error = {} // Error greeting
Private var process: download_process = {DownloadedSize, Length, Process ->} // Progress
PRIVATE VAR SUCCESS: Dowload_suCcess = {} // Download completion
Private Val Context: context = myapplication.context // Global Context
Var seturi: () -> URI? = {null} // Set the downloaded URI
Var setFileName: () -> string? = {null} // set file name
fun process(process: DOWLOAD_PROCESS) {
this.process = process
}
fun error(error: DOWLOAD_ERROR) {
this.error = error
}
fun success(success: DOWLOAD_SUCCESS) {
this.success = success
}
suspend fun startDowload() {
withContext(Dispatchers.IO) {
try {
Val body = response.body ()?: throw runtimeException ("Download error")
// File total length
val length = body.contentLength()
// File MineType
val contentType = body.contentType()?.toString()
val ios = body.byteStream()
var uri: Uri? = null
var file: File? = null
val ops = kotlin.run {
setUri()?.let {
// URL turn OutputStream
uri = it
context.contentResolver.openOutputStream(it)
} ?: kotlin.run {
val fileName = setFileName() ?: kotlin.run {
// If you don't even give it, you will generate a file name.
"${System.currentTimeMillis()}.${MimeTypeMap.getSingleton()
.getExtensionFromMimeType(contentType)}"
}
file =
File("${context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)}${File.separator}$fileName")
FileOutputStream(file)
}
}
// Download the length
var currentLength: Int = 0
// Write file
val bufferSize = 1024 * 8
val buffer = ByteArray(bufferSize)
val bufferedInputStream = BufferedInputStream(ios, bufferSize)
var readLength: Int = 0
while (bufferedInputStream.read(buffer, 0, bufferSize)
.also { readLength = it } != -1
) {
ops.write(buffer, 0, readLength)
currentLength += readLength
process(
currentLength.toLong(),
length,
currentLength.toFloat() / length.toFloat()
)
}
bufferedInputStream.close()
ops.close()
ios.close()
if (uri != null) {
success(uri!!)
} else if (file != null) {
success(Uri.fromFile(file))
}
} catch (e: Exception) {
error(e)
}
}
}
}
.