首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Android 10作用域存储(Mediastore Entry & File)中删除图像

如何在Android 10作用域存储(Mediastore Entry & File)中删除图像
EN

Stack Overflow用户
提问于 2021-06-28 13:47:32
回答 3查看 1.4K关注 0票数 6

当我试图删除一个图片,已经被贡献/拥有我的应用程序,它可以很容易地删除。但是对于我的应用程序尚未拥有的Pictures文件夹中的共享媒体,我通过捕捉RecoverableSecurityException向用户显示提示。但是即使在允许之后,我也无法删除特定的图像文件。

这是我正在使用的代码,请指出我做错了什么。

  • 删除后图像不会出现在图片库或我的应用程序中,但它会留在文件管理器中,在电话重新启动后返回到图片库(我猜只有MediaStore条目被删除了)
  • 该代码在Android 11设备上运行良好。
  • startIntentSenderForResult(intentSender, 12, null, 0, 0, 0, null);的结果是RESULT_OK

用于获取文件:(此代码在我的活动中)

代码语言:javascript
运行
复制
   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类中)

代码语言:javascript
运行
复制
    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):

代码语言:javascript
运行
复制
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);
    
        }
    }
}}
EN

回答 3

Stack Overflow用户

发布于 2021-12-05 17:28:31

井。有两种方法可以实现。他们中的一个也将在android 11上工作。我不是在说requestLegacyExternalStorage的许可。你也可以这样做,顺便说一下。

在Android10中,如果不使用requestLegacyExternalStorage权限或Storage Access Framework (DocumentsProvider way),则必须为每个文件获取删除文件权限。

要做到这一点,请检查此方法。

对于Android 10:

代码语言:javascript
运行
复制
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的替代品出现在这里,因为它被从Android11中删除。

以下是您如何声明的:

代码语言:javascript
运行
复制
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();
                }
            }
        }
);

它将提示一个对话框删除图像。如果用户允许,那么它将删除该图像,没有任何问题。

对于Android 11:

代码语言:javascript
运行
复制
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中的多个图像,那么可以使用选项,或“DocumentsProvider”API.

除此之外,这两种方法是完美的。

是的,如果你想用Mediastore API保存安卓10及以上版本的图片,那么看看这篇文章,它会给你很大的帮助。

票数 2
EN

Stack Overflow用户

发布于 2021-10-27 19:47:09

我还没有对它进行测试,但我认为您需要集成自定义行为,以便在处理低于Q的构建时使用。

代码语言:javascript
运行
复制
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();
            }
票数 1
EN

Stack Overflow用户

发布于 2021-11-03 12:49:28

在安卓清单中添加android:requestLegacyExternalStorage="false"。允许范围内的存储。

对于低于Android10的版本,请将android:requestLegacyExternalStorage设置为false

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68164496

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档