Android Q RecoverableSecurityException 未授予访问权限

Android Q RecoverableSecurityException not granting access

我正在尝试对 Android API 29 的文件处理进行排序。由于我对 Android 上与文件相关的任何事情都不是明星,所以我 运行 成问题了。

当我将图像添加到我的应用程序时,我可以使用 contentResolver.delete(deleteUri, null, null); 删除它们并且一切正常。但是当应用程序被删除然后重新安装时,它给了我一个 RecoverableSecurityException,这是考虑到的,我已经这样做了,所以请求文件的权限才能删除它。当授予权限并且我试图再次删除该文件时,它仍然给我 android.app.RecoverableSecurityException: **app**.debug has no access to content://media/external/images/media/280。它已从 ContentResolver 中删除,因为它在任何画廊中都不再可见,并且在查询时 returns 没有结果,但该文件仍然 "physically" 在设备上。

我需要在哪里查找才能解决此问题? ContentResolver 只有一个结果,它在不同错误中显示的文件路径(与上述错误一起显示)是正确的:E/MediaProvider: Couldn't delete /storage/emulated/0/Pictures/**app**/**filename**.jpeg

删除文件功能:

Cursor c = getCursorFromContentResolver(fileName);

        if (c != null && c.moveToFirst())
        {
            long id = c.getLong(c.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
            Uri deleteUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
            try
            {
                contentResolver.delete(deleteUri, null, null);
            }catch (RecoverableSecurityException e)
            {
                //After the below Intent returns, the current function is run again
                activity.startIntentSenderForResult(e.getUserAction().getActionIntent().getIntentSender(), requestCode, null, 0, 0, 0, null);
            }
            c.close();
            return true;
        }

请求其他权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

我在 Android Q 中遇到了一个非常相似的问题,当使用内容解析器删除调用删除图像时。事实证明,尽管我捕获了 RecoverableSecurityException 以获得从 android 图库中删除图像的权限 - 它仍然抛出一个错误,它无法删除文件,因为应用程序没有权限(因此在打开 Google 照片它将扫描图像并找到 "undeleted" 使它返回的照片)。这是我看到与您的问题相同的错误的地方。当我在 Android 上尝试相同的代码时,R 文件没有返回。

阅读此问题后,我尝试使用 SAF 作为解决方案。我设法永久删除图像的方法是使用 Intent.ACTION_OPEN_DOCUMENT_TREE

让用户进入 select 图像目录(在我的例子中是 DCIM/Camera)

然后我在按下删除按钮时捕获了父文件夹的 Uri 和该文件夹中文件的名称:

 String filename = queryUriName(content, photoUri);

 DocumentFile docF = DocumentFile.fromTreeUri(context,myTree);
 Boolean docex = docF.exists();
 String idDoc = DocumentsContract.getTreeDocumentId(myTree);
 idDoc = idDoc + "/"+filename;
 Uri childrenUri = DocumentsContract.buildDocumentUriUsingTree(myTree,idDoc);

 DocumentFile childfile = DocumentFile.fromSingleUri(context,childrenUri);
 Boolean chex = childfile.exists();
 System.out.println("child exist: "+ chex+ " file name is " + filename +"   "+idDoc);

这允许删除实际文件,据我所知,它不会抛出任何错误,文件也已消失。

请谨慎使用,因为我已经进入 android 开发工作约 3 周,无法在其他地方找到所描述的问题或解决方案。但如果需要,我们很乐意扩展或更新答案。

以防万一,如果有人希望从 android 10 开始 RecoverableSecurityException 在你的 catch 块中处理

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            if(e instanceof  RecoverableSecurityException){
                RecoverableSecurityException recoverableSecurityException =  (RecoverableSecurityException) e;
                IntentSender intentSender = recoverableSecurityException.getUserAction().getActionIntent().getIntentSender();
                if(intentSender != null){
                    try {
                        startIntentSender(intentSender, null, 0, 0, 0);
                    } catch (IntentSender.SendIntentException sendIntentException) {
                        sendIntentException.printStackTrace();
                    }
                }
            }
        }