Android MediaStore.Images.Media.insertImage已弃用
我以前使用Android MediaStore.Images.Media.insertImage已弃用,android,mediastore,Android,Mediastore,我以前使用MediaStore.images.Media.insertImage保存图像,但insertImage方法现在已不推荐使用。他们说: 此方法在API级别29中被弃用。应插入图像 可以使用,这提供了更丰富的 对生命周期的控制 我真的不明白,因为MediaColumns.u PENDING只是一个标志,我应该如何使用它 我应该使用ContentValues 解决 @commonware中建议的代码没有问题,但如果您使用targetSdkVersion 29编程,则必须添加以下条件: va
MediaStore.images.Media.insertImage
保存图像,但insertImage
方法现在已不推荐使用。他们说:
此方法在API级别29中被弃用。应插入图像
可以使用,这提供了更丰富的
对生命周期的控制
我真的不明白,因为MediaColumns.u PENDING
只是一个标志,我应该如何使用它
我应该使用ContentValues
解决
@commonware中建议的代码没有问题,但如果您使用targetSdkVersion 29
编程,则必须添加以下条件:
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis().toString())
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //this one
put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation)
put(MediaStore.MediaColumns.IS_PENDING, 1)
}
}
此方法在API级别29中被弃用。应插入图像
使用MediaColumns#IS_PENDING执行,这提供了更丰富的
对生命周期的控制
要么我太傻了,不懂文档,要么谷歌团队真的需要重构文档
无论如何,发布由和提供的完整答案
第1步:决定您的API级别
步骤2:以Q样式保存图像
第3步:如果未启用Q以传统样式保存图像
这会让你兴奋的 感谢您在上的贡献
步骤2:以Q样式保存图像
我在Android Studio中遇到了一些内存使用问题,我不得不打开Sublime进行修复。要修复此错误,请执行以下操作:
e:java.lang.OutOfMemoryError:java堆空间
这是我使用的代码,因为我的用例用于PNG图像,bitmap.compress的任何值小于100都可能没有用处。
以前的版本在API 30上不起作用,所以我将contentValues相对路径更新为目录\u DCIM
也contentResolver.insert(外部内容URI,
private val dateFormatter=SimpleDateFormat(
“yyyy.MM.dd”位于“HH:MM:ss z”,Locale.getDefault()
)
private val legacyOrQ:(位图)->Uri={if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.Q)
saveImageInQ(it)else legacySave(it)}
private fun saveImageInQ(位图:位图):Uri{
val filename=“${dateFormatter.format(Date())}.png的${title}u”
输出流?
val contentValues=contentValues()。应用{
put(显示名称、文件名)
put(MIME_类型,“图像/png”)
put(相对路径、目录\u DCIM)
put(正在挂起,1)
}
//使用应用程序上下文获取contentResolver
val contentResolver=applicationContext.contentResolver
val uri=contentResolver.insert(外部内容uri,contentValues)
uri?.let{contentResolver.openOutputStream(it)}。也{fos=it}
fos?使用{bitmap.compress(bitmap.CompressFormat.PNG,100,it)}
fos?.flush()
fos?.close()
contentValues.clear()
contentValues.put(正在挂起,0)
乌里?让我来{
update(it,contentValues,null,null)
}
返回uri!!
}
步骤3:如果不在Q上,则以传统样式保存图像
private-fun-legacySave(位图:位图):Uri{
val appContext=applicationContext
val filename=“${dateFormatter.format(Date())}.png的${title}u”
val directory=getExternalStoragePublicDirectory(目录图片)
val file=file(目录,文件名)
val outStream=FileOutputStream(文件)
compress(bitmap.CompressFormat.PNG,100,扩展)
溢流
流出。关闭()
MediaScannerConnection.scanFile(appContext,arrayOf(file.absolutePath),
空,空)
返回FileProvider.getUriForFile(appContext,${appContext.packageName}.provider“,
文件)
}
步骤4:创建自定义文件提供程序
package com.example.background.workers.provider
导入androidx.core.content.FileProvider
类WorkerFileProvider:FileProvider(){
}
步骤5:更新您的AndroidManifest.xml
改变
到
步骤6:在xml下为文件提供程序路径添加资源
在我的情况下,我需要图片文件夹
我正在添加第二个答案,因为我不确定是否有人关心版本检查,但如果您执行了他们的步骤,嗯。。。
从
步骤5:更新您的AndroidManifest.xml
改变
使用ContentValues
调用insert()
带有的项被设置为0
。请参见示例,尽管在我的示例中,我保存的是视频,而不是图像。问题:这段代码中发生了什么:uri?。让{resolver.openOutputStream(uri)?。使用{outputStream->val sink=Okio.buffer(Okio.sink(outputStream))response.body()?.source()?.let{sink.writeAll(it)}sink.close()}
在我的情况下,我正在从URL下载视频到设备。response.body().source()
给我一个Okiosource
表示我正在下载的视频字节。Okio.buffer(Okio.sink(outputStream))
给我一个OkioSink
表示我将字节写入的位置,以及writeAll()
wri
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) saveImageInQ(imageBitMap)
else saveImageInLegacy(imageBitMap)
//Make sure to call this function on a worker thread, else it will block main thread
fun saveImageInQ(bitmap: Bitmap):Uri {
val filename = "IMG_${System.currentTimeMillis()}.jpg"
var fos: OutputStream? = null
val imageUri: Uri? = null
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
put(MediaStore.Video.Media.IS_PENDING, 1)
}
//use application context to get contentResolver
val contentResolver = application.contentResolver
contentResolver.also { resolver ->
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
}
fos?.use { bitmap.compress(Bitmap.CompressFormat.JPEG, 70, it) }
contentValues.clear()
contentValues.put(MediaStore.Video.Media.IS_PENDING, 0)
resolver.update(uri, values, null, null)
return imageUri
}
//Make sure to call this function on a worker thread, else it will block main thread
fun saveTheImageLegacyStyle(bitmap:Bitmap){
val imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val image = File(imagesDir, filename)
fos = FileOutputStream(image)
fos?.use {bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)}
}
<activity android:name=".MyActivity" />
<activity android:name=".legacy.LegacyMyActivity"/>
<activity android:name=".MyActivity" />
<provider
android:name=".workers.provider.WorkerFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true"
android:enabled="@bool/atMostKitkat"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER"/>
</intent-filter>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
<activity-alias android:name=".legacy.LegacyMyActivity"
android:targetActivity=".MyActivity"
android:enabled="@bool/atMostJellyBeanMR2">
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.OPENABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/png" />
</intent-filter>
</activity-alias>