我正在尝试使用以下代码保存从相机拍摄的图像:
@RequiresApi(Build.VERSION_CODES.Q)
private fun setImageUri(): Uri {
val resolver = contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "house2.jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/OLArt")
}
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
return imageUri!!
}
该功能第一次运行良好。但是当图像 (house2.jpg) 已经存在时,系统将创建另一个名为“house2 (1).jpg”、“house2 (2).jpg”等的文件(而不是替换旧文件)
我可以在 contentValues 中设置什么来强制解析器替换文件而不是创建它的副本吗?
下面是拍照 Intent 的代码。
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, setImageUri()) //<- i paste in the imageUri here
// Ensure that there's a camera activity to handle the intent
takePictureIntent.resolveActivity(packageManager)?.also {
startActivityForResult(takePictureIntent, 102)
}
}
最佳答案
@CommonsWare 的评论有所帮助。
这个想法是
创建查询选择时要注意的一件事是 MediaStore.MediaColumns.RELATIVE_PATH 需要终止“/”
即 'Pictures/OLArt/' << 注意 OLArt/之后的斜线
val selection = "${MediaStore.MediaColumns.RELATIVE_PATH}='Pictures/OLArt/' AND "
+ "${MediaStore.MediaColumns.DISPLAY_NAME}='house2.jpg' "
以下是更新后的代码。
@RequiresApi(Build.VERSION_CODES.Q)
private fun getExistingImageUriOrNullQ(): Uri? {
val projection = arrayOf(
MediaStore.MediaColumns._ID,
MediaStore.MediaColumns.DISPLAY_NAME, // unused (for verification use only)
MediaStore.MediaColumns.RELATIVE_PATH, // unused (for verification use only)
MediaStore.MediaColumns.DATE_MODIFIED //used to set signature for Glide
)
// take note of the / after OLArt
val selection = "${MediaStore.MediaColumns.RELATIVE_PATH}='Pictures/OLArt/' AND "
+ "${MediaStore.MediaColumns.DISPLAY_NAME}='house2.jpg' "
contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, selection, null, null ).use { c ->
if (c != null && c.count >= 1) {
print("has cursor result")
c.moveToFirst().let {
val id = c.getLong(c.getColumnIndexOrThrow(MediaStore.MediaColumns._ID) )
val displayName = c.getString(c.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME) )
val relativePath = c.getString(c.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH) )
lastModifiedDate = c.getLong(c.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED) )
imageUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
print("image uri update $displayName $relativePath $imageUri ($lastModifiedDate)")
return imageUri
}
}
}
print("image not created yet")
return null
}
然后我将此方法添加到我现有的代码中
@RequiresApi(Build.VERSION_CODES.Q)
private fun setImageUriQ(): Uri {
val resolver = contentResolver
imageUri = getExistingImageUriOrNullQ() //try to retrieve existing uri (if any)
if (imageUri == null) {
//=========================
// existing codes for resolver.insert
//(SNIPPED)
//=========================
}
return imageUri!!
}
关于android - MediaStore contentResolver.insert() 在拍照时创建副本而不是替换现有文件(Android Q : 29),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60632273/