我曾经使用< code>MediaStore保存图像。Images.Media.insertImage,但< code>insertImage方法现在已被否决。医生说:
此方法在 API 级别 29 中已弃用。应使用 MediaColumns#IS_PENDING 执行图像的插入,这样可以更丰富地控制生命周期。
我不太明白,因为<code>媒体列。IS_PENDING只是一个标志,我应该如何使用它?
我应该使用 ContentValues 吗
?
感谢您在步骤2:以Q样式保存图像时贡献iCantC。
我在Android Studio中遇到了一些内存使用问题,我不得不打开Sublime进行修复。要修复此错误,请执行以下操作:
e: java.lang.OutOfMemoryError: Java heap space
这是我使用的代码,因为我的用例是用于PNG图像,<code>位图的任何值。压缩小于100可能没有用处。以前的版本不适用于API 30,因此我将contentValues<code>RELATIVE_PATH
private val dateFormatter = SimpleDateFormat(
"yyyy.MM.dd 'at' HH:mm:ss z", Locale.getDefault()
)
private val legacyOrQ: (Bitmap) -> Uri = { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
saveImageInQ(it) else legacySave(it) }
private fun saveImageInQ(bitmap: Bitmap): Uri {
val filename = "${title}_of_${dateFormatter.format(Date())}.png"
val fos: OutputStream?
val contentValues = ContentValues().apply {
put(DISPLAY_NAME, filename)
put(MIME_TYPE, "image/png")
put(RELATIVE_PATH, DIRECTORY_DCIM)
put(IS_PENDING, 1)
}
//use application context to get contentResolver
val contentResolver = applicationContext.contentResolver
val uri = contentResolver.insert(EXTERNAL_CONTENT_URI, contentValues)
uri?.let { contentResolver.openOutputStream(it) }.also { fos = it }
fos?.use { bitmap.compress(Bitmap.CompressFormat.PNG, 100, it) }
fos?.flush()
fos?.close()
contentValues.clear()
contentValues.put(IS_PENDING, 0)
uri?.let {
contentResolver.update(it, contentValues, null, null)
}
return uri!!
}
步骤3:如果未启用Q,则以传统样式保存图像
private fun legacySave(bitmap: Bitmap): Uri {
val appContext = applicationContext
val filename = "${title}_of_${dateFormatter.format(Date())}.png"
val directory = getExternalStoragePublicDirectory(DIRECTORY_PICTURES)
val file = File(directory, filename)
val outStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream)
outStream.flush()
outStream.close()
MediaScannerConnection.scanFile(appContext, arrayOf(file.absolutePath),
null, null)
return FileProvider.getUriForFile(appContext, "${appContext.packageName}.provider",
file)
}
第4步:创建自定义FileProvider
package com.example.background.workers.provider
import androidx.core.content.FileProvider
class WorkerFileProvider : FileProvider() {
}
第五步:更新AndroidManifest.xml
更改自
<activity android:name=".MyActivity" />
到
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.PICK"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.OPENABLE"/>
<data android:mimeType="image/png"/>
</intent-filter>
</activity>
<provider
android:name=".workers.provider.WorkerFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true"
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>
步骤6:在xml下为FILE_PROVIDER_path添加一个资源
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="pictures" path="Pictures"/>
</paths>
此方法在API级别29中已弃用。插入图像应使用MediaClons#IS_PENDING执行,它提供了对生命周期的更丰富控制。
要么我太笨了,无法理解文档,要么谷歌团队真的需要重构文档。
无论如何,从CommonsWare和coroutineDispatcher提供的链接发布完整的答案
步骤1:决定您的API级别
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) saveImageInQ(imageBitMap)
else saveImageInLegacy(imageBitMap)
第2步:以Q样式保存图像
//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(imageUri, contentValues, null, null)
return imageUri
}
步骤3:如果未启用Q,则以传统样式保存图像
//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)}
}
这应该让你滚!
解决了的
@CommonsWare建议的代码没有任何问题,除非您使用< code>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)
}
}
我正在尝试获取uri和后解析为纵隔图像的路径。我这样做是为了获取URI: 在使用此函数之后,我转换路径中的uri: 但结果是,我有媒体存储的路径,但有第一个元素。例如:。但我只想要。 请不要告诉我使用连接和拆分,因为这不是我想要的。
我试图在我的代码中使用Bodyparser,但代码被编辑器本身剪切,并表示Bodyparser已被弃用。我尝试了一些我在网上找到的替代代码,但都不起作用。附件是我正在使用的代码的截图。密码 代码:
我想在谷歌地图上存储一些POI(兴趣点),只在android应用程序中使用 然后我想检索用户当前位置“x”km范围内的所有POI 所以,问题是:是否有可能将自定义数据存储在谷歌地图上供应用程序私人使用?(请提供任何示例的链接) 要存储的任何其他完全管理的解决方案
我一直在研究这个问题,在提交我的代码后,7个案例通过了,然而,9个案例失败了。问题链接位于HackerRank:电子商店 问题陈述 一个女孩想买一个键盘和一个USB驱动器,她想尽可能多地花钱,但要在预算内(将这两个项目结合起来)。如果这两件物品的价格都超过了她的预算,那么退货-1,否则她就买不到了。强制性的是,她想买这两件东西,而不是一件。 例子 一系列键盘以数组的形式给出,USB驱动器以。现在,
URL release环境: https://skill.rokid.com/storev2