【发布时间】:2021-08-20 21:39:57
【问题描述】:
我有一个自定义 DocumentsProvider 实现,只要 Android API 为 26 或更高版本,用户就可以完美地选择应用使用的照片或视频。使用 API 21-25 时,我收到类似于this SO 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>
我的 Intent 设置如下所示:
Context context = InTouch.getInstance().getApplicationContext();
Intent contentSelectionIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("*/*");
引用此意图的启动器如下所示:
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 是 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION,由我的提供者通过这篇文章顶部的清单条目,3 是值的组合 (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)。
然而,当我尝试使用 takePersistableUriPermission() API 时,使用该意图返回的关联 Uri 以及上面的 'takeFlags' 参数 (initialIntent.getFlags() & URI_PERMISSIONS_FLAGS) 的 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)。
如果我使用 API 21 使用 SAF 尝试我的应用程序,并从应用程序特定区域之外的手机中选择一些东西(因此不包含我的自定义 DocumentsProvider),它也可以工作。
因此,我认为这是我在运行 API 21-25 的设备的自定义 DocumentsProvider 中没有做的事情,但我不知道这可能是什么。
实现自定义 DocumentsProvider 有什么不同,这可能会影响获取 API 21 到 25 与 26 及更高版本的持久权限的能力?
我假设从错误中进行某种协调以匹配从选择器返回的 Uri 与最初启动选择器的 Intent,但我不明白这种关系是如何工作的,在哪里开始寻找调试它,或者我什至在这个假设的正确轨道上。
【问题讨论】:
-
代码太多。我们应该去哪里看。?哪个语句会产生该错误?
URI_PERMISSIONS_FLAGS为什么是你自己的宏?只需使用我们都知道的标志。你又添加了一个。很多复杂的代码。为什么需要两个 uri 数组列表来向我们展示您的问题?请发布最少的代码。 -
但总的来说:您应该只尝试获取提供给您的权限。
-
我使用自己的常量(不是宏),因为我在任何地方都使用相同的两个权限,实际上它比每次都拼出它们更简单。
-
在 ACTION_OPEN_DOCUMENT 的意图中设置这些标志是没有意义的。他们什么都不做。您最好删除它们以获得更清晰的代码。
-
你只是重复你的代码。为什么?我们已经看到了。把那些标志拿出来,看看它们没有效果。
标签: android android-contentprovider android-contentresolver storage-access-framework