Andrfoid 11 通过Glide下载图片音视频等文件,使用 MediaStore 和 ContentResolver 将文件保存到公共目录,跳过MANAGE_EXTERNAL_STORAGE权限

    fun downloadFile(url: String) {
        Glide.with(this).asFile().load(url).listener(object : RequestListener<File?> {
            override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<File?>?, isFirstResource: Boolean): Boolean {
                return false
            }

            override fun onResourceReady(resource: File?, model: Any?, target: Target<File?>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                saveFile(this@FlowActivity, resource, "image")
                return false
            }
        }).submit()

    }

    fun saveFile(context: Context, file: File?, mimeType: String): Uri? {
        var folderName = "Pictures"
        var extension = ".jpg"
        when (mimeType) {
            "gif" -> {
                extension = ".gif"
            }
            "image" -> {
                extension = ".jpg"
            }
            "video" -> {
                extension = ".mp4"
                folderName = "Movies"
            }
            "audio" -> {
                extension = ".mp3"
                folderName = "Music"
            }
            "pdf" -> {
                extension = ".pdf"
                folderName = "Documents"
            }
        }
        if (Build.VERSION.SDK_INT >= 29) {
            val values = ContentValues()
            values.put(MediaStore.Files.FileColumns.MIME_TYPE, mimeType)
            values.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000)
            values.put(MediaStore.Files.FileColumns.DATE_TAKEN, System.currentTimeMillis())
            values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, folderName)
            values.put(MediaStore.Files.FileColumns.IS_PENDING, true)
            values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, "file_" + System.currentTimeMillis() + extension)
            var uri: Uri? = null
            when {
                mimeType.contains("image") -> {
                    uri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
                }
                mimeType.contains("video") -> {
                    uri = context.contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
                }
                mimeType.contains("audio") -> {
                    uri = context.contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values)
                }
                mimeType.contains("pdf") -> {
                    uri = context.contentResolver.insert(MediaStore.Files.getContentUri("external"), values)
                }
            }
            uri?.apply {
                runCatching {
                    saveFileToStream(contentResolver.openInputStream(Uri.fromFile(file))!!, contentResolver.openOutputStream(uri)!!)
                    values.put(MediaStore.Video.Media.IS_PENDING, false)
                    context.contentResolver.update(this, values, null, null)
                    return this
                }.getOrElse {
                    return null
                }
            }
        }
        return null
    }

    private fun saveFileToStream(input: InputStream, outputStream: OutputStream) {
        input.use { input ->
            runCatching {
                outputStream.use { output ->
                    val buffer = ByteArray(4 * 1024) // or other buffer size
                    var read: Int
                    while (input.read(buffer).also { read = it } != -1) {
                        output.write(buffer, 0, read)
                    }
                    output.flush()
                }
            }
        }
    }

写了个工具类方法

//把照片和视频复制一份到相册
fun copyFileToGallery(file: File, fileName: String) {
    val resolver: ContentResolver = MyApp.instance.contentResolver
    val values = ContentValues()

    val uriSavedVideo: Uri? = if (Build.VERSION.SDK_INT >= 29) {
        values.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000)
        values.put(MediaStore.Files.FileColumns.DATE_TAKEN, System.currentTimeMillis())
        values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, "Pictures/kkone")
        values.put(MediaStore.Files.FileColumns.IS_PENDING, true)
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, fileName)
        if (fileName.contains("JPG")) {
            values.put(MediaStore.Files.FileColumns.MIME_TYPE, "image")
            resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        } else {
            values.put(MediaStore.Files.FileColumns.MIME_TYPE, "video")
            resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
        }

    } else {
        values.put(MediaStore.Files.FileColumns.TITLE, fileName)
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, fileName)
        values.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000)
        if (fileName.contains("JPG")) {
            values.put(MediaStore.Files.FileColumns.MIME_TYPE, "image")
            resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        } else {
            values.put(MediaStore.Files.FileColumns.MIME_TYPE, "video")
            resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
        }

    }
    uriSavedVideo?.apply {
        runCatching {
            val pfd = resolver.openFileDescriptor(this, "w") as ParcelFileDescriptor
            val out = FileOutputStream(pfd.fileDescriptor)
            val `in` = FileInputStream(file)
            val buf = ByteArray(8192)
            var len: Int
            while (`in`.read(buf).also { len = it } > 0) {
                out.write(buf, 0, len)
            }
            out.close()
            `in`.close()
            pfd.close()
        }
        if (Build.VERSION.SDK_INT >= 29) {
            values.clear()
            values.put(MediaStore.Files.FileColumns.IS_PENDING, 0)
            resolver.update(this, values, null, null)
        }
    }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值