When I try to delete an image that has been contributed/owned by my app it can be deleted easily. But for shared media inside the Pictures folder that my app has not owned, I show users a prompt by catching RecoverableSecurityException
. But even after ALLOWING, I'm not able to delete that particular image file.
Here's the code I'm using, please point out what am I doing wrong.
startIntentSenderForResult(intentSender, 12, null, 0, 0, 0, null);
is RESULT_OK
For fetching files: (This code is in My Activity)
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();
}
For Deleting Image Files: (This code is in my Adapter class)
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();
}
}
Prompting the user (Inside My Activity to get 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);
}
}
}}
Well. There are 2 methods to do it. One of them will work on android 11 as well.
I am not talking about the requestLegacyExternalStorage
permission here.
You can also do it that way, btw.
In Android 10, You have to take delete files permission for each file if you're not using requestLegacyExternalStorage
permission or the Storage Access Framework (DocumentsProvider way)
.
To do that, check this method.
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);
}
}
}
Now, the deleteResultLauncher
stands here as an alternative of the onActivityResult()
API replacement as it's deprecated from android 11.
Here is how you declare it :
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();
}
}
}
);
It will prompt a dialog to delete the image. If user allows it, then it will delete that image without any problem.
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);
}
The declaration of the deleteResultLauncher
is the same here as shown above.
Second method is more useful here, as it can be used to delete multiple images at a time. But unfortunately, it starts from Android 11. It's not available in android 10. So if you want to delete multiple images in android 10, then you can go with requestLegacyExternalStorage
option, or 'DocumentsProvider' API.
Apart from that, these two methods are perfect for the cause.
And yes, If you want to save the images in Android 10 & above versions with Mediastore API
, then have a look at this article, it will help you a lot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With