• Android 保存图片并刷新相册(无需权限)


    一、背景

    之前的保存图片吧,在Android11之前,我会去申请WIRITE权限,11之后,我又去申请MANAGE_EXTERNAL_STORAGE这个权限,该权限将授权读写所有共享存储内容,这也将同时包含非媒体类型的文件。但是在google上架的时候,MANAGE_EXTERNAL_STORAGE属于敏感权限,需要向谷歌做声明,做了,没过,谷歌说可以不要这个权限也可以保存,看来是我无知了,于是去研究了一下下,有了下面的方法。

    二、实现

    1. @SuppressLint("UseCompatLoadingForDrawables")
    2. @AfterPermissionGranted(200)
    3. fun saveFreshAppImageToGallery(context: PreViewActivity, imageResId: Int) {
    4. val drawable = context.getDrawable(imageResId)
    5. if (drawable is BitmapDrawable) {
    6. val bitmap = drawable.bitmap
    7. val displayName = "${System.currentTimeMillis()}.jpg"
    8. val values = ContentValues().apply {
    9. put(MediaStore.Images.Media.DISPLAY_NAME, displayName)
    10. put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
    11. put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000)
    12. }
    13. val contentResolver = context.contentResolver
    14. val collection =
    15. MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    16. val item = contentResolver.insert(collection, values)
    17. item?.let { uri ->
    18. try {
    19. val outputStream = contentResolver.openOutputStream(uri)
    20. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
    21. outputStream?.close()
    22. Toast.makeText(context, "Save successfully!", Toast.LENGTH_SHORT).show()
    23. val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
    24. mediaScanIntent.data = uri
    25. context.sendBroadcast(mediaScanIntent)
    26. } catch (e: Exception) {
    27. Toast.makeText(context, "Save Failed!", Toast.LENGTH_SHORT).show()
    28. e.printStackTrace()
    29. }
    30. }
    31. }
    32. }

    其中:通知相册刷新的逻辑是下面代码

    val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
    mediaScanIntent.data = uri
    context.sendBroadcast(mediaScanIntent)

    或者下面的方法

    1. private fun saveToGallery(photoFile: File) {
    2. val contentValues = ContentValues().apply {
    3. put(MediaStore.Images.Media.DISPLAY_NAME, "photo.jpg")
    4. put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
    5. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    6. put(MediaStore.Images.Media.IS_PENDING, 1)
    7. }
    8. }
    9. val contentResolver = contentResolver
    10. val collectionUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    11. MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    12. } else {
    13. MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    14. }
    15. val imageUri = contentResolver.insert(collectionUri, contentValues)
    16. imageUri?.let { uri ->
    17. try {
    18. contentResolver.openOutputStream(uri)?.use { outputStream ->
    19. val inputStream = FileInputStream(photoFile)
    20. inputStream.copyTo(outputStream)
    21. inputStream.close()
    22. outputStream.close()
    23. }
    24. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    25. contentValues.clear()
    26. contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
    27. contentResolver.update(uri, contentValues, null, null)
    28. }
    29. } catch (e: IOException) {
    30. }
    31. }
    32. }

    原理都是一样的

  • 相关阅读:
    clang llc llvm-link llvm-config 应用示例
    今年的数据安全风险点是什么?看数据
    并发的三大特性
    Maven 私服搭建指南
    fully_connected与linear
    Linux日志管理
    什么台灯最好学生晚上用?开学适合学生用的护眼台灯推荐
    【SpringMVC拦截器】
    K8S Pod
    西邮计科嵌入式复习
  • 原文地址:https://blog.csdn.net/LoveFHM/article/details/133298130