gpt4 book ai didi

android - 尝试通过 ACTION_OPEN_DOCUMENT 获取自定义 DocumentsProvider 的 PersistableUriPermission() 失败

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:12:25 27 4
gpt4 key购买 nike

我正在尝试编写一个自定义 DocumentsProvider,它允许其他应用程序对其提供的 Uris 获取持久权限

我有一个 DocumentsProvider,我在我的 AndroidManufest.xml 中声明如下

<provider
android:name="com.cgogolin.myapp.MyContentProvider"
android:authorities="com.cgogolin.myapp.MyContentProvider"
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS"
android:enabled="@bool/atLeastKitKat">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>

我的应用程序具有 MANAGE_DOCUMENTS 权限集

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

(显然这不是必需的,但添加/删除它也无关紧要)。然后,当我使用

打开 ACTION_OPEN_DOCUMENT 选择器 UI 时,我可以看到我的提供者
Intent openDocumentIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
openDocumentIntent.addCategory(Intent.CATEGORY_OPENABLE);
openDocumentIntent.setType("application/pdf");
openDocumentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION|Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(openDocumentIntent, EDIT_REQUEST);

并且,在我的应用程序的 onActivityResult() 方法中从我的提供者那里选择了一个文件之后,我可以通过Uri 我从 intent.getData() 获得。

但是,尝试使用

保留读取或写入权限
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

总是失败并出现异常

No permission grant found for UID 10210 and Uri content://com.cgogolin.myapp.MyContentProvider/document/tshjhczf.pdf

如果我在选择器 UI 中从谷歌驱动器或下载提供程序中选择一个文件,以这种方式获得权限是可行的。所以我认为问题出在我的提供者身上。

尽管我指定了 android:grantUriPermissions="true" 为什么没有创建权限授予?

我如何说服 Android 为我创建这样的权限授予?

毕竟我认为我自己做不到,因为我不知道打开选择器 UI 的进程的 UID,或者至少我不知道该怎么做。

最佳答案

编辑:

我之前的回答不好。出于安全原因,您应该使用“android.permission.MANAGE_DOCUMENTS”。
只有系统 UI 选择器才能列出您的文档。

但在打开文档的应用程序的 list 中,您不需要此权限
实际上你不应该获得这个权限,因为它是系统权限。

我刚刚对其进行了测试,并成功调用了 onActivityResult 中的 takePersistableUriPermission 表单。

我使用带有模拟数据的 DocumentProvider(一个根,3 个 txt 文档)。
如果它仍然不适合您,则可能是您的文档提供程序存在问题。

编辑 2:

示例代码

package com.example.test;

import android.database.Cursor;
import android.database.MatrixCursor;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsProvider;

import java.io.FileNotFoundException;

public class MyContentProvider extends DocumentsProvider {

private final static String[] rootColumns = new String[]{
"_id", "root_id", "title", "icon"
};
private final static String[] docColumns = new String[]{
"_id", "document_id", "_display_name", "mime_type", "icon"
};

MatrixCursor matrixCursor;
MatrixCursor matrixRootCursor;

@Override
public boolean onCreate() {

matrixRootCursor = new MatrixCursor(rootColumns);
matrixRootCursor.addRow(new Object[]{1, 1, "TEST", R.mipmap.ic_launcher});

matrixCursor = new MatrixCursor(docColumns);
matrixCursor.addRow(new Object[]{1, 1, "a.txt", "text/plain", R.mipmap.ic_launcher});
matrixCursor.addRow(new Object[]{2, 2, "b.txt", "text/plain", R.mipmap.ic_launcher});
matrixCursor.addRow(new Object[]{3, 3, "c.txt", "text/plain", R.mipmap.ic_launcher});

return true;
}

@Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
return matrixRootCursor;
}

@Override
public Cursor queryDocument(String documentId, String[] projection)
throws FileNotFoundException {

return matrixCursor;
}

@Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
String sortOrder)
throws FileNotFoundException {

return matrixCursor;
}

@Override
public ParcelFileDescriptor openDocument(String documentId, String mode,
CancellationSignal signal)
throws FileNotFoundException {

int id;
try {
id = Integer.valueOf(documentId);
} catch (NumberFormatException e) {
throw new FileNotFoundException("Incorrect document ID " + documentId);
}

String filename = "/sdcard/";

switch (id) {
case 1:
filename += "a.txt";
break;
case 2:
filename += "b.txt";
break;
case 3:
filename += "c.txt";
break;
default:
throw new FileNotFoundException("Unknown document ID " + documentId);
}

return ParcelFileDescriptor.open(new File(filename),
ParcelFileDescriptor.MODE_READ_WRITE);
}
}

注意:
您可以使用 DocumentsContract.DocumentDocumentsContract.Root 中的常量。
我不确定是否需要“_id”。

编辑 3:

更新了示例代码以从/sdcard 打开文档。
添加了读/写外部存储权限。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.example.test"
xmlns:android="http://schemas.android.com/apk/res/android">

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

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">

<provider
android:name="com.example.test.MyContentProvider"
android:authorities="com.example.test.document"
android:enabled="true"
android:exported="@bool/atLeastKitKat"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER"/>
</intent-filter>
</provider>
</application>

</manifest>

客户端应用

具有空 Activity 的新项目,添加了无权限

打开文档

Intent openDocumentIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
openDocumentIntent.addCategory(Intent.CATEGORY_OPENABLE);
openDocumentIntent.setType("text/plain");
openDocumentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(openDocumentIntent, 1);

onActivityResult

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1: // TODO: Use constant
if (resultCode == RESULT_OK) {
if (data == null) return; // TODO: Show error
Uri uri = data.getData();
if (uri == null) return; // TODO: Show error
getContentResolver().takePersistableUriPermission(uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);

InputStream is = null;
try {
is = getContentResolver().openInputStream(uri);

// Just for quick sample (I know what I will read)
byte[] buffer = new byte[1024];
int read = is.read(buffer);
String text = new String(buffer, 0, read);

((TextView) findViewById(R.id.text)).setText(text);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
break;
}
}

关于android - 尝试通过 ACTION_OPEN_DOCUMENT 获取自定义 DocumentsProvider 的 PersistableUriPermission() 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34331956/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com