![](/img/trans.png)
[英]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.