[英]Android 10 scoped storage how to delete the underlying image file in a shared directory
[英]How to delete an Image in Android 10 Scoped Storage (Mediastore Entry & File)
当我尝试删除由我的应用程序提供/拥有的图像时,它可以轻松删除。 但是对于我的应用程序不拥有的图片文件夹中的共享媒体,我通过捕获RecoverableSecurityException
向用户显示提示。 但即使在ALLOWING之后,我也无法删除该特定图像文件。
这是我正在使用的代码,请指出我做错了什么。
startIntentSenderForResult(intentSender, 12, null, 0, 0, 0, null);
结果正常用于获取文件:(此代码在我的活动中)
try {
String DIRECTORY_NAME = "%Pictures/App_Name%";
String selection = MediaStore.MediaColumns.RELATIVE_PATH + " like ? ";
String[] selectionArgs = new String[]{DIRECTORY_NAME};
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null);
while(cursor.moveToNext()){
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
Uri contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
uriArrayList.add(contentUri);
}
cursor.close();
}
catch (Exception e){
e.printStackTrace();
}
用于删除图像文件:(此代码在我的 Adapter 类中)
try {
ContentResolver contentResolver = context.getContentResolver();
cachedUri = f; //f is Uri
contentResolver.delete(f, null, null);
}catch (SecurityException securityException) {
RecoverableSecurityException recoverableSecurityException;
if (securityException instanceof RecoverableSecurityException) {
recoverableSecurityException =
(RecoverableSecurityException) securityException;
} else {
throw new RuntimeException(
securityException.getMessage(), securityException);
}
IntentSender intentSender = recoverableSecurityException.getUserAction()
.getActionIntent().getIntentSender();
try {
resultInterface.onResultTaken(intentSender, cachedUri); //Giving a call to the activity that implements the interface
} catch (Exception e) {
e.printStackTrace();
}
}
提示用户(在我的活动中获取 onActivityResult):
public class SomeActivity extends AppCompatActivity implements ResultTakenListener{
protected void onCreate(){
...}
@Override
public void onResultTaken(IntentSender intentSender, Uri uri) throws IntentSender.SendIntentException {
cacheduri = uri;
startIntentSenderForResult(intentSender, 12, null, 0, 0, 0, null);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 12){
Log.d("Result Code is-->", String.valueOf(resultCode)); //This gives RESULT_OK
if(resultCode == RESULT_OK){
ContentResolver contentResolver = this.getContentResolver();
contentResolver.delete(cacheduri, null, null);
}
}
}}
我尚未对其进行测试,但我认为当您处理低于 Q 的构建时,您需要集成自定义行为。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//your existing code that seems to work above Q
} else {
String docsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File file = new File(docsDir, "fileName.jpg");
if(file.exists());
file.delete();
}
在您的 android 清单中添加android:requestLegacyExternalStorage="false"
。 这允许范围存储。
对于 android 10 以下的版本,将android:requestLegacyExternalStorage
设置为false
。
好。 有2种方法可以做到。 其中之一也适用于 android 11。 我不是在这里谈论requestLegacyExternalStorage
权限。 你也可以这样做,顺便说一句。
在 Android 10 中,如果您不使用requestLegacyExternalStorage
权限或Storage Access Framework (DocumentsProvider way)
则必须为每个文件获取删除文件权限。
为此,请检查此方法。
public static void deleteImageAPI29(Context context, Uri uri) {
ContentResolver resolver = context.getContentResolver();
try {
resolver.delete(uri, null, null);
} catch (SecurityException securityException) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
RecoverableSecurityException recoverableSecurityException = (RecoverableSecurityException) securityException;
IntentSenderRequest senderRequest = new IntentSenderRequest.Builder(recoverableSecurityException.getUserAction()
.getActionIntent().getIntentSender()).build();
deleteResultLauncher.launch(senderRequest);
}
}
}
现在, deleteResultLauncher
在这里作为onActivityResult()
API 替代品的替代品,因为它已从 android 11 中弃用。
这是您声明它的方式:
ActivityResultLauncher<IntentSenderRequest> deleteResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == RESULT_OK){
Toast.makeText(context, "Image deleted.", Toast.LENGTH_SHORT).show();
}
}
}
);
它将提示一个对话框以删除图像。 如果用户允许,那么它将毫无问题地删除该图像。
public void deleteImageAPI30(Context context, ArrayList<Media> arrayList) {
ContentResolver contentResolver = context.getContentResolver();
ArrayList<Uri> arrayList2 = new ArrayList();
for (int i = 0; i < arrayList.size(); i++) {
arrayList2.add(arrayList.get(i).getUri()); // You need to use the Uri you got using ContentUris.withAppendedId() method
}
Collections.addAll(arrayList2);
IntentSender intentSender = MediaStore.createDeleteRequest(contentResolver, arrayList2).getIntentSender();
IntentSenderRequest senderRequest = new IntentSenderRequest.Builder(intentSender)
.setFillInIntent(null)
.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 0)
.build();
deleteResultLauncher.launch(senderRequest);
}
deleteResultLauncher
的声明与上图相同。
第二种方法在这里更有用,因为它可用于一次删除多个图像。 但不幸的是,它从 Android 11 开始。它在 android 10 中不可用。因此,如果您想在 android 10 中删除多个图像,那么您可以使用requestLegacyExternalStorage
选项或“DocumentsProvider”API。
除此之外,这两种方法非常适合这个原因。
是的,如果您想使用Mediastore API
保存 Android 10 及以上版本中的图像,请查看本文,它将对您有很大帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.