如何删除我在Android Q 中创建的文件?
How to delete file created by me in Android Q?
我正在 DCIM 目录中保存图像,但在某些情况下,我需要将其删除。
以前,我只调用了 image.delete(),其中图像是文件。但现在这张图片以另一种方式保存:
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM" + File.separator + IMAGES_FOLDER_NAME);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
boolean saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
我尝试使用它的名称进行查询并调用 contentResolver.delete(...),但它不起作用。
我有写入外部存储的权限,但我不想使用 SAF。
如何删除这样的文件?
您需要使用调用插入时获得的 Uri
ContentResolver
的 delete
方法。
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
boolean saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
......
int result = resolver.delete(imageUri, null, null);
if (result > 0) {
Log.d("Tag", "File deleted");
}
如果您没有存储 Uri,则需要执行 query()
,检索内容,然后调用 delete
。
File file = new File(delPath);
if (file.exists()) {
try {
Uri imageUri = FileProvider.getUriForFile(Context,
getApplicationContext()
.getPackageName() + ".provider", file);
ContentResolver contentResolver = getContentResolver();
int deletefile = contentResolver.delete(imageUri, null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
这里的删除路径delPath
是你要从存储中删除的图片的文件路径。
完整的解决方案还应包括处理在尝试使用 ContentResolver 删除时 Andorid Q 上可能发生的潜在错误。在这种情况下,您应该将代码包装在 try/catch 块中。
以下解决方案:
try {
// 1
getApplication<Application>().contentResolver.delete(
imageUri,"${MediaStore.Images.Media._ID} = ?",
arrayOf(imageId)
)
}
// 2
catch (securityException: SecurityException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val recoverableSecurityException =
securityException as? RecoverableSecurityException
?: throw securityException
val intentSender = recoverableSecurityException.userAction.actionIntent.intentSender
startIntentSenderForResult(
intentSender,
DELETE_PERMISSION_REQUEST,
null,
0,
0,
0,
null
)
} else {
throw securityException
}
}
在这里,您在 try 块内调用 contentResolver.delete(),因为此方法会在运行时抛出 SecurityException。该方法需要您要删除的图像的 ContentUri。在 where 参数中,您指定要根据图像的 _ID 删除图像。在最后一个参数中,您在数组中传递 _ID 的字符串版本。
在 Android 10 及更高版本中,无法直接从 MediaStore 中删除或修改项目。您需要获得这些操作的许可。正确的做法是先捕获RecoverableSecurityException,它包含一个intentSender,可以提示用户授予权限。然后,您使用从 RecoverableSecurityException 中提取的 intentSender 启动 IntentSenderForResult,以授予在 Android Q.
上删除文件的额外权限
来源:https://www.raywenderlich.com/9577211-scoped-storage-in-android-10-getting-started
intent.addFlags 在调用方法 startActivityForResult 之前。
像这样
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
因为它在 ContentProvider#enforceWritePermissionInner 中检查权限。
真正的实现在 ActivityManagerService#checkPermission 方法中。
我正在 DCIM 目录中保存图像,但在某些情况下,我需要将其删除。 以前,我只调用了 image.delete(),其中图像是文件。但现在这张图片以另一种方式保存:
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM" + File.separator + IMAGES_FOLDER_NAME);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
boolean saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
我尝试使用它的名称进行查询并调用 contentResolver.delete(...),但它不起作用。
我有写入外部存储的权限,但我不想使用 SAF。
如何删除这样的文件?
您需要使用调用插入时获得的 Uri
ContentResolver
的 delete
方法。
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
boolean saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
......
int result = resolver.delete(imageUri, null, null);
if (result > 0) {
Log.d("Tag", "File deleted");
}
如果您没有存储 Uri,则需要执行 query()
,检索内容,然后调用 delete
。
File file = new File(delPath);
if (file.exists()) {
try {
Uri imageUri = FileProvider.getUriForFile(Context,
getApplicationContext()
.getPackageName() + ".provider", file);
ContentResolver contentResolver = getContentResolver();
int deletefile = contentResolver.delete(imageUri, null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
这里的删除路径delPath
是你要从存储中删除的图片的文件路径。
完整的解决方案还应包括处理在尝试使用 ContentResolver 删除时 Andorid Q 上可能发生的潜在错误。在这种情况下,您应该将代码包装在 try/catch 块中。 以下解决方案:
try {
// 1
getApplication<Application>().contentResolver.delete(
imageUri,"${MediaStore.Images.Media._ID} = ?",
arrayOf(imageId)
)
}
// 2
catch (securityException: SecurityException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val recoverableSecurityException =
securityException as? RecoverableSecurityException
?: throw securityException
val intentSender = recoverableSecurityException.userAction.actionIntent.intentSender
startIntentSenderForResult(
intentSender,
DELETE_PERMISSION_REQUEST,
null,
0,
0,
0,
null
)
} else {
throw securityException
}
}
在这里,您在 try 块内调用 contentResolver.delete(),因为此方法会在运行时抛出 SecurityException。该方法需要您要删除的图像的 ContentUri。在 where 参数中,您指定要根据图像的 _ID 删除图像。在最后一个参数中,您在数组中传递 _ID 的字符串版本。
在 Android 10 及更高版本中,无法直接从 MediaStore 中删除或修改项目。您需要获得这些操作的许可。正确的做法是先捕获RecoverableSecurityException,它包含一个intentSender,可以提示用户授予权限。然后,您使用从 RecoverableSecurityException 中提取的 intentSender 启动 IntentSenderForResult,以授予在 Android Q.
上删除文件的额外权限
来源:https://www.raywenderlich.com/9577211-scoped-storage-in-android-10-getting-started
intent.addFlags 在调用方法 startActivityForResult 之前。 像这样
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
因为它在 ContentProvider#enforceWritePermissionInner 中检查权限。
真正的实现在 ActivityManagerService#checkPermission 方法中。