保存图片到手机相册

在 AndroidManifest.xml 文件中添加权限:

1
2
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

保存图片的缩略图 thumbnail

将 Bitmap 图片下载到相册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//下载图片到相册时,存储图片的url
private var mUri:Uri? = null

fun download(bitmap: Bitmap){
//我到相册对应 uri 地址
val uri = if(VERSION.SDK_INT> VERSION_CODES.Q){
MediaStore.lmages.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
}else{
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}

//****************************************************************************** 传统方式 将图片插入到设备的媒体库中
//将当前的图片地址配置一下
val contentValues = ContentValues().apply { this: ContentValues
put(MediaStore.lmages.Media.DISPLAY_NAME,TimeUtils.timeName()) //图片名称
put(MediaStore.lmages.Media.MIME_TYPE,"image/jpeg") //MIME 类型
}

//图片在相册里面的具体 uri
val imageUri = requireActivity().contentResolver.insert(uri,contentValues)
//******************************************************************************

//------------------------------------------高于 11 版本方式
if(VERSION.SDK_INT > VERSION_CODES.R){
MediaStore.createWriteRequest(requireActivity().contentResolver, listOf(imageUri))
}
//------------------------------------------

//输出流
requireContext().contentResolver.openOutputStream(imageUril!!).use{it:OutputStream?
val result = bitmap.compress(Bitmap.CompressFormat.JPEG, quality: 100,it)
if (result){
Toast.makeText(requireContext(), text:"保存成功",Toast.LENGTH_LONG).show()
mUri = imageUril
}else{
Toast.makeText(requireContext(), text:"保存失败",Toast.LENGTH_LONG).show()
mUri = null
}
}

}

获取相册 uri

if (VERSION.SDK_INT > VERSION_CODES.Q) 是根据当前设备的Android版本来选择不同的存储图片的URI。
这样做的目的是因为在不同的Android版本中,系统提供的API和存储机制可能会有所不同。

在Android Q(10)及以上的版本中,Google引入了Scoped Storage (作用域存储)的概念,对应用程序访问外部存储的方式进行了改变。
在Scoped Storage中,应用程序只能访问自己的应用特定目录,而无法直接访问外部存储的任意文件。
因此,如果设备的Android版本大于Android Q,就需要使用新的方式来获取存储图片的 URI

  • 即使用 MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)

而在Android Q以下的版本中,应用程序可以直接访问外部存储中的文件,因此可以使用传统的方式获取存储图片的URI,

  • 即使用MediaStore.Images.Media.EXTERNAL_CONTENT_URI

通过根据Android版本来选择不同的URI获取方式,可以确保应用程序在不同版本的Android设备上都能正确地保存图片到相册中,以适应不同版本的存储机制和权限要求。
这样的做法可以提高应用程序的兼容性和稳定性,确保其在不同设备上的正常运行。

MediaStore.createWriteRequest()

这段代码是在Android应用中使用了Android 11(Android R)及以上版本的特定功能。让我们逐步解释这段代码:

  1. if(VERSION.SDK_INT > VERSION_CODES.R):这段代码检查当前设备的Android版本是否高于Android 11(即Android R)。SDK_INT是一个表示设备当前Android版本的整数常量,VERSION_CODES.R代表Android 11。因此,这行代码的作用是判断当前设备的Android版本是否高于Android 11。

  2. MediaStore.createWriteRequest(requireActivity().contentResolver, listOf(imageUri)):如果当前设备的Android版本高于Android 11,那么会执行这行代码。
    该代码调用了MediaStore.createWriteRequest方法,传入了Activity的ContentResolver和包含了图片URI的List集合。

为什么要这样做?
在Android 11中,引入了Scoped Storage(作用域存储)的概念,这就意味着应用程序无法直接访问设备上的文件系统路径。
相反,应用程序必须通过系统提供的 API 来请求对文件的访问权限。
在这种情况下,MediaStore.createWriteRequest方法被用来请求写入权限以便应用程序能够将图片插入到设备的媒体库中
这种方式旨在增强设备的安全性和隐私保护,确保应用程序只能访问到其被授权的文件和媒体内容。

1
2
3
if(VERSION.SDK_INT > VERSION_CODES.R){
MediaStore.createWriteRequest(requireActivity().contentResolver, listOf(imageUri))
}

如果设备的Android版本高于Android 11,则调用MediaStore.createWriteRequest方法来创建一个写入请求,传入当前活动的contentResolver和一个包含imageUri的列表。

保存原图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//下载图片到相册时,存储图片的url
private var mUri:Uri? = null

fun download(filePath:String){
val file = File(filePath)
if(!file.exist()) return

//我到相册对应 uri 地址
val uri = if(VERSION.SDK INT> VERSION CODES.Q){
MediaStore.lmages.Media.getContentUri(MediaStore.VOLUME EXTERNAL PRIMARY
}else{
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}

//将当前的图片地址配置一下
val contentValues = ContentValues().apply { this: ContentValues
put(MediaStore.lmages.Media.DISPLAY_NAME,TimeUtils.timeName())
put(MediaStore.lmages.Media.MIME_TYPE,"image/jpeg")
}

//图片在相册里面的具体uri
val imageUri = requireActivity().contentResolver.insert(uri,contentValues)

if(VERSION.SDK_INT > VERSION_CODES.R){
MediaStore.createWriteRequest(requireActivity().contentResolver, listOf(imageUri))
}

//输出流
requireContext().contentResolver.openOutputStream(imageUril!!).use{ os ->

BufferedInputStream(FilelnputStream(file)).use{ bis ->
val bufferArray = ByteArray(size: 1024)
//从输入流中读数据到 bufferArray 中
var len = bis.read(bufferArray, off: 0,len: 1024)

while (len > 0){
//读多少个就写多少个
os!!.write(bufferArray, off: 0,len)
//写完了一次再继续读 为下次读写做准备
len = bis.read(bufferArray, off: 0, len: 1024)
}

//冲干净
os!!.flush()
Toast.makeText(requireContext(), text:"保存成功",Toast.LENGTH LONG).show()
mUri = imageUri

}

}

}

创建输入流对象

输入流的不断往输出流中写

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信