簡體   English   中英

如何刪除 Android 10 Scoped Storage 中的圖像(媒體存儲條目和文件)

[英]How to delete an Image in Android 10 Scoped Storage (Mediastore Entry & File)

當我嘗試刪除由我的應用程序提供/擁有的圖像時,它可以輕松刪除。 但是對於我的應用程序不擁有的圖片文件夾中的共享媒體,我通過捕獲RecoverableSecurityException向用戶顯示提示。 但即使在ALLOWING之后,我也無法刪除該特定圖像文件。

這是我正在使用的代碼,請指出我做錯了什么。

  • 刪除后圖像不會出現在圖庫或我的應用程序中,但它保留在文件管理器中並在手機重新啟動后出現在圖庫中(我猜只有 MediaStore 條目被刪除)
  • 該代碼適用於 Android 11 設備。
  • 結果來自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)則必須為每個文件獲取刪除文件權限。

為此,請檢查此方法。

對於安卓 10:

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();
                }
            }
        }
);

它將提示一個對話框以刪除圖像。 如果用戶允許,那么它將毫無問題地刪除該圖像。

對於安卓 11:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM