当前位置: 首页 > 知识库问答 >
问题:

如何在Android 10作用域存储中删除图像(Mediastore条目

罗河
2023-03-14

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

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

  • 图像在删除后不会出现在图库或我的应用程序中,但它会保留在文件管理器中,并在手机重新启动后重新出现在图库中(我猜只有MediaStore条目被删除)
  • 该代码适用于Android 11设备。
  • 来自start IntentSenderForResult(intentSender,12, null,0,0, null)的结果;RESULT_OK

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

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

用于删除图像文件:(此代码在我的适配器类中)

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

共有3个答案

石思淼
2023-03-14

在您的android清单中添加android: Request estLegacyExternalStorage="false"。这允许范围存储。

对于android 10以下的版本,将android: Request estLegacyExternalStorage设置为false

佘缪文
2023-03-14

好有两种方法可以做到这一点。其中一个也将在android 11上工作。我这里不是指requestLegacyExternalStorage权限。顺便说一句,你也可以这样做。

在Android 10中,如果您没有使用Request estLegacyExternalStorage权限或Storage Access Framework(DocumentsProvider方式),则必须为每个文件获取删除文件权限。

为此,请检查此方法。

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。

除此之外,这两种方法非常适合这一原因。

是的,如果您想在Android 10中保存图像

滕鸿畴
2023-03-14

我还没有测试它,但我认为当您处理低于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 Q 范围存储的链接。 根据此Android开发者最佳实践博客,(这是我的情况)应使用MediaStore API完成。 深入研究文档,我找不到相关功能。 这是我在科特林的审判: 结果是,按照最佳做法博客中的描述,我的图像保存在此处为 我的问题是: 如何使用MediaStore API保存图像? 用Java回答同样可以接受。 提前致谢! 编辑 感谢PerracoL

  • 我有一个Laravel项目,我试图用Storage::delete删除图像,但它似乎不起作用。我的图像位于storage\app\public\uploads文件夹中。我可以上传和编辑图像,但删除不起作用。我使用的是Laravel 8。 产品控制器。PHP PHP 网状物PHP 配置/文件系统。PHP

  • 我正在开发一个功能,以删除上传的文件。我目前可以删除云Firestore中的引用,但无法将其从存储中删除。下面的代码应该从存储中删除,但它不起作用 错误消息是“没有请求的auth标记。StorageException已发生。对象在位置不存在。HttpResult:404”。我以为这个问题与我的fileUrl字段有关,但我不确定。fileUrl是下载图像的url,例如,如果我将url复制并粘贴到we

  • 我正在OS X 10.8.4(Mountain Lion)下的Vagrant下运行Docker,每当我试图删除一个保存的图像时,我会得到一个错误: 根据帮助,正确的语法是,我不知道该如何解释。 如何删除图像?   有趣的是,当我运行时,根本没有容器显示。运行将显示四(4)个图像和一(1)个图像。

  • 我有以下图片: 当我试图移除其中一个时,我得到: 我怎样才能移除它们?为什么会有这样的冲突?

  • 问题内容: 已关闭 。这个问题需要细节或说明。它当前不接受答案。 想改善这个问题吗? 添加详细信息并通过编辑此帖子来澄清问题。 6年前关闭。 请给我查询在MySQL数据库中插入图像的查询。我是stackoverflow的新手,所以如果我的问题不符合要求,请忽略我。 问题答案: 有特定的原因为什么您不能存储对图像的引用,而不是实际图像? 图像很大,它们使数据库很大。SQL可能很痛苦(因为它不是面向对