通过 ACTION_OPEN_DOCUMENT 的 takePersistableUriPermission 在自定义文档提供程序上失败,但仅适用于 API < 26
takePersistableUriPermission via ACTION_OPEN_DOCUMENT fails on a custom documents provider but only for API < 26
我有一个自定义的 DocumentsProvider 实现,只要 Android API 为 26 或更大,用户就可以完美地选择照片或视频供应用使用。使用 APIs 21-25 我得到一个类似于 this SO post 中描述的安全错误。但是,我已经在做 post 中提到的所有事情作为解决方案。
清单条目:
<provider
android:name=".storageproviders.FacebookProvider"
android:authorities="${facebookDocumentsAuthority}"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
我的意图设置如下所示:
Context context = InTouch.getInstance().getApplicationContext();
Intent contentSelectionIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("*/*");
引用此 Intent 的启动器如下所示:
mLaunchFileChooserIntent = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if ( result.getResultCode() == Activity.RESULT_OK) {
Intent initialIntent = result.getData();
if ( initialIntent != null) {
// This may have one or more files
ArrayList<Uri> uriList = new ArrayList<>();
Uri uri = initialIntent.getData();
if (uri != null) {
// Single file chosen
uriList.add(uri);
} else {
*
*
*
}
// I then call my utility method handleMediaClipData() passing the following as the argument for 'takeFlags':
// (initialIntent.getFlags() & URI_PERMISSIONS_FLAGS)
该启动器的使用是作为对按下按钮的响应来完成的,如下所示:
mFiles.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
closeFABMenu();
mLaunchFileChooserIntent.launch(contentSelectionIntent);
}
});
我已经使用模拟器 运行 API 21 验证了从 SAF 选择器(上面的initialIntent
)返回的意图将其标志设置为 0x43,即正确 - 0x40 是我的提供商通过此 post 顶部的清单条目提供的 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
,3 是值 (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
.
的组合
然而,当我尝试使用 takePersistableUriPermission()
API 使用该意图返回的关联 Uri 以及上面的 flags 参数时 'takeFlags' 参数 (initialIntent.getFlags() & URI_PERMISSIONS_FLAGS)
像这样:
public static Disposable handleMediaClipData(final MediaCreate mediaCreate,
final ArrayList<Uri> mediaUris,
final int takeFlags,
final String listId,
final AppCompatActivity activity) {
Context context = InTouch.getInstance().getApplicationContext();
final ContentResolver resolver = context.getContentResolver();
*
*
*
resolver.takePersistableUriPermission(uri, takeFlags);
*
*
*
我收到以下安全错误:
java.lang.SecurityException: No persistable permission grants found for UID 10084
使用 API 26 或更高版本的模拟器和物理设备上完全相同的代码流(应用程序 ui,自定义 DocumentsProvider)。
如果我使用 SAF 使用 API 21 尝试我的应用程序并从应用程序特定区域之外的 phone 中选择一些东西(因此不包含我的自定义 DocumentsProvider),它也可以工作。
因此,我认为这是我在设备的自定义 DocumentsProvider 中没有做的事情 运行 API 21-25 但我不知道那可能是什么。
实施自定义 DocumentsProvider 有何不同,这可能会影响为 API 21 至 25 与 26 及更高级别获取持久权限的能力?
我从错误中假设在幕后进行了某种协调,以匹配从选择器返回的 Uri 与最初启动选择器的 Intent,但我不明白这种关系是如何工作的,从哪里开始调试它,或者我是否在这个假设的正确轨道上。
您对 DocumentsProvider
的实施没有任何问题,这是 API 19-25 使用 SAF 时的预期行为。
即使您在尝试获得持久 URI 许可时获得 SecurityException
,您仍然始终可以访问从您自己的 DocumentsProvider
.
公开的 URI
因此,最好从您自己的 URI 中捕获并忽略 SecurityException
。
Note: If your app contains a DocumentsProvider and also persists URIs returned from ACTION_OPEN_DOCUMENT, ACTION_OPEN_DOCUMENT_TREE, or ACTION_CREATE_DOCUMENT, be aware that you won’t be able to persist access to your own URIs via takePersistableUriPermission() — despite it failing with a SecurityException, you’ll always have access to URIs from your own app. You can add the boolean EXTRA_EXCLUDE_SELF to your Intents if you want to hide your own DocumentsProvider(s) on API 23+ devices for any of these actions.
这是来自官方 Android 开发者博客的注释,证实了此行为 - https://medium.com/androiddevelopers/building-a-documentsprovider-f7f2fb38e86a
我有一个自定义的 DocumentsProvider 实现,只要 Android API 为 26 或更大,用户就可以完美地选择照片或视频供应用使用。使用 APIs 21-25 我得到一个类似于 this SO post 中描述的安全错误。但是,我已经在做 post 中提到的所有事情作为解决方案。
清单条目:
<provider
android:name=".storageproviders.FacebookProvider"
android:authorities="${facebookDocumentsAuthority}"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
我的意图设置如下所示:
Context context = InTouch.getInstance().getApplicationContext();
Intent contentSelectionIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("*/*");
引用此 Intent 的启动器如下所示:
mLaunchFileChooserIntent = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if ( result.getResultCode() == Activity.RESULT_OK) {
Intent initialIntent = result.getData();
if ( initialIntent != null) {
// This may have one or more files
ArrayList<Uri> uriList = new ArrayList<>();
Uri uri = initialIntent.getData();
if (uri != null) {
// Single file chosen
uriList.add(uri);
} else {
*
*
*
}
// I then call my utility method handleMediaClipData() passing the following as the argument for 'takeFlags':
// (initialIntent.getFlags() & URI_PERMISSIONS_FLAGS)
该启动器的使用是作为对按下按钮的响应来完成的,如下所示:
mFiles.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
closeFABMenu();
mLaunchFileChooserIntent.launch(contentSelectionIntent);
}
});
我已经使用模拟器 运行 API 21 验证了从 SAF 选择器(上面的initialIntent
)返回的意图将其标志设置为 0x43,即正确 - 0x40 是我的提供商通过此 post 顶部的清单条目提供的 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
,3 是值 (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
.
然而,当我尝试使用 takePersistableUriPermission()
API 使用该意图返回的关联 Uri 以及上面的 flags 参数时 'takeFlags' 参数 (initialIntent.getFlags() & URI_PERMISSIONS_FLAGS)
像这样:
public static Disposable handleMediaClipData(final MediaCreate mediaCreate,
final ArrayList<Uri> mediaUris,
final int takeFlags,
final String listId,
final AppCompatActivity activity) {
Context context = InTouch.getInstance().getApplicationContext();
final ContentResolver resolver = context.getContentResolver();
*
*
*
resolver.takePersistableUriPermission(uri, takeFlags);
*
*
*
我收到以下安全错误:
java.lang.SecurityException: No persistable permission grants found for UID 10084
使用 API 26 或更高版本的模拟器和物理设备上完全相同的代码流(应用程序 ui,自定义 DocumentsProvider)。
如果我使用 SAF 使用 API 21 尝试我的应用程序并从应用程序特定区域之外的 phone 中选择一些东西(因此不包含我的自定义 DocumentsProvider),它也可以工作。
因此,我认为这是我在设备的自定义 DocumentsProvider 中没有做的事情 运行 API 21-25 但我不知道那可能是什么。
实施自定义 DocumentsProvider 有何不同,这可能会影响为 API 21 至 25 与 26 及更高级别获取持久权限的能力?
我从错误中假设在幕后进行了某种协调,以匹配从选择器返回的 Uri 与最初启动选择器的 Intent,但我不明白这种关系是如何工作的,从哪里开始调试它,或者我是否在这个假设的正确轨道上。
您对 DocumentsProvider
的实施没有任何问题,这是 API 19-25 使用 SAF 时的预期行为。
即使您在尝试获得持久 URI 许可时获得 SecurityException
,您仍然始终可以访问从您自己的 DocumentsProvider
.
因此,最好从您自己的 URI 中捕获并忽略 SecurityException
。
Note: If your app contains a DocumentsProvider and also persists URIs returned from ACTION_OPEN_DOCUMENT, ACTION_OPEN_DOCUMENT_TREE, or ACTION_CREATE_DOCUMENT, be aware that you won’t be able to persist access to your own URIs via takePersistableUriPermission() — despite it failing with a SecurityException, you’ll always have access to URIs from your own app. You can add the boolean EXTRA_EXCLUDE_SELF to your Intents if you want to hide your own DocumentsProvider(s) on API 23+ devices for any of these actions.
这是来自官方 Android 开发者博客的注释,证实了此行为 - https://medium.com/androiddevelopers/building-a-documentsprovider-f7f2fb38e86a