【问题标题】:How can i reach GrantUriPermission problem without Open_Document filedialog?如果没有 Open_Document 文件对话框,我如何解决 GrantUriPermission 问题?
【发布时间】:2022-01-20 12:23:22
【问题描述】:

我想在外部 PDF 查看器中打开文件。 如果我使用“OPEN_DOCUMENT”文件选择器调用该文件,一切正常。

如果我在没有用户对话框的情况下直接使用硬编码的现有 URI 调用不同的文件,我没有权限。

得到这个错误:

 Caused by: java.lang.SecurityException: UID 10153 does not have permission to content://com.android.externalstorage.documents/document/primary%3ANot%2FBar%2Ftest.pdf [user 0]; you could obtain access using ACTION_OPEN_DOCUMENT or related APIs
    at android.os.Parcel.createException(Parcel.java:2071)
    at android.os.Parcel.readException(Parcel.java:2039)
    at android.os.Parcel.readException(Parcel.java:1987)
    at android.app.IActivityManager$Stub$Proxy.grantUriPermission(IActivityManager.java:5748)
    at android.app.ContextImpl.grantUriPermission(ContextImpl.java:1935)
    at android.content.ContextWrapper.grantUriPermission(ContextWrapper.java:805)
    at android.content.ContextWrapper.grantUriPermission(ContextWrapper.java:805)
    at de.temaks.stepbystep.MainActivity.grantPermissions(MainActivity.java:203)
    at de.temaks.stepbystep.MainActivity.oPDF(MainActivity.java:184)
    at de.temaks.stepbystep.MainActivity.my10(MainActivity.java:144)
    at java.lang.reflect.Method.invoke(Native Method) 
    at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:441) 
    at android.view.View.performClick(View.java:7146) 
    at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119) 
    at android.view.View.performClickInternal(View.java:7119) 
    at android.view.View.access$3500(View.java:803) 
    at android.view.View$PerformClick.run(View.java:27533) 
    at android.os.Handler.handleCallback(Handler.java:883) 
    at android.os.Handler.dispatchMessage(Handler.java:100) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7386) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980) 
 Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.server.uri.UriGrantsManagerService.checkGrantUriPermission(UriGrantsManagerService.java:1174)
    at com.android.server.uri.UriGrantsManagerService.grantUriPermission(UriGrantsManagerService.java:767)
    at com.android.server.uri.UriGrantsManagerService$LocalService.grantUriPermission(UriGrantsManagerService.java:1317)

我尝试使用 ACTION_OPEN_DOCUMENT_TREE 设置文件夹中所有文件的标志:

public void openDirectory(Uri uriToLoad) {
// Choose a directory using the system's file picker.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);

// Optionally, specify a URI for the directory that should be opened in
// the system file picker when it loads.
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriToLoad);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

startActivityForResult(intent, 3333);

} 并且在 activityRusult 尝试为该文件夹中的所有文件设置标志:

            if (requestCode == 3333
            && resultCode == Activity.RESULT_OK) {
        // The result data contains a URI for the document or directory that
        // the user selected.
        Uri uri = null;
        if (resultData != null) {
            uri = resultData.getData();
            // Perform operations on the document using its URI.
            Log.i("Verzeichnis ", "gelesen: "+uri.toString());

            //take persist permission for later use
            getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

            int takeFlags = resultData.getFlags()& (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            ContentResolver resolver = this.getContentResolver();
            resolver.takePersistableUriPermission(resultData.getData(),takeFlags);
            File directory = new File(path);

            Log.i("directory.exists():   ",String.valueOf(directory.exists()));
            Log.i("directory.canRead():  ",String.valueOf( directory.canRead()));
            Log.i("directory.length():   ",String.valueOf( directory.length()));
 
            /*File[] files = directory.listFiles();
            Log.i("Files", "Size: " + files.length);
            Toast.makeText(this,String.valueOf(files.length) +" 

            String[] theNamesOfFiles = new String[files.length];
            for (int i = 0; i < files.length; i++) {  
                    theNamesOfFiles[i] =  files[i].getName(); 
             }*/

这不起作用,因为之后的错误仍然相同。 也许我有错误的标志?

directory.exists() 给出“真”

directory.canRead() 给出“假”

我将标志设置为“目录树”。 我应该在每个文件上单独设置标志吗?

目前在测试用例中,我手动构建了 uri(这个 uri(文件)在我设置标志的树中)。稍后我想从数据库中调用已保存的 uri。

Uri uri2 = Uri.parse("content://com.android.externalstorage.documents/document/primary%3ANoten_MVP%2FBariton%2F0018_Wiener%20Elan-Bariton.pdf");
oPDF(uri2);

将 uri 发送到外部应用程序:

    public void oPDF(Uri myUri){
    Uri uri = null;

    uri = myUri;

    uri.getAuthority();

    String mimeType = getContentResolver().getType(uri);

    Log.i("mime Type ", mimeType);

    //this.grantUriPermission(null, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

    Log.i("URI Import",uri.toString());

    String path = uri.getLastPathSegment()  ;//getEncodedPath();
    path = path.substring(path.indexOf(":") + 1);
    Toast.makeText(this, "importiert: " + path, Toast.LENGTH_LONG).show();

    Log.i("READ_REQUEST_CODE 42: "," hier sind die Ergebnisse aus onActivityResult: " );
    Log.i("uri DER: ", uri.toString());

    Intent target = new Intent(Intent.ACTION_VIEW);
    //target.setDataAndType(Uri.parse("content://com.android.externalstorage.documents/document/primary%3A"+ path), "application/pdf");
    target.setDataAndType(uri, "application/pdf");
    target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    //Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    Intent intent = Intent.createChooser(target, "Open PDF using");
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    grantPermissions(this,target,uri,true);
    try {
        startActivity(intent);
    } catch (ActivityNotFoundException e) {
        // Instruct the user to install a PDF reader here, or something
        Toast.makeText(this, "No Applications found to open pdf", Toast.LENGTH_SHORT).show();
    }
}

还是一样的错误

原因:java.lang.SecurityException:UID 10153 没有对内容的权限://com.android.externalstorage.documents/document/primary%3ANoten_MVP%2FBariton%2F0010_Laridah%20Marsch-Bariton.pdf [user 0] ;您可以使用 ACTION_OPEN_DOCUMENT 或相关 API 获得访问权限

如何获取文件夹中所有文件的权限? 我能做什么?

【问题讨论】:

  • target.setDataAndType(uri, "application/pdf"); 你没有展示你是如何建立你的uri的。
  • 我的 uri 存在且正确。
  • 你应该只调用一次 takePersistableUriPermission()。

标签: java android android-studio uri permission-denied


【解决方案1】:

一旦您看到一些使用 ACTION_OPEN_DOCUMENT 获得的文件,就可以为文件建立良好的 uri。

但是通过 ACTION_OPEN_DOCUMENT,内容提供者(或操作系统,告诉我!)也允许您使用该 uri。并记住他们!

你现在所感知的:

原因:java.lang.SecurityException:UID 10153 没有权限访问内容://com.android.externalstorage.documents/document/primary%3ANot%2FBar%2Ftest.pdf [user 0];您可以使用 ACTION_OPEN_DOCUMENT 或相关 API 获得访问权限

是你没有获得使用你的uri的权限。

【讨论】:

  • 我的 uri 正确且存在。
  • 我需要访问文件夹中的所有文件(mybay 数百个文件)。手动打开 ACTION_OPEN_DOCUMENT 中的每个文件是不可能的。这就是为什么我正在寻找一种解决方案来获得完整文件夹及其中文件的权限。
  • 这很简单。让用户选择带有 ACTION_OPEN_DOCUMENT_TREE 的文件夹。然后你就拥有了其中所有文件的权限。
  • 好的,很高兴知道!权限是否仅在 onActionResult 中? - 或者也可以从以后的功能中访问。也适用于外部应用程序?
  • 已获得用户许可:在您的应用在该设备上的整个生命周期内。
猜你喜欢
  • 2019-10-12
  • 2012-01-28
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 2021-02-16
  • 2020-12-02
  • 1970-01-01
  • 2011-03-07
相关资源
最近更新 更多