Android 与 FileProvider 共享文件时,带有 grantUriPermission 的 SecurityException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21275898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:16:12  来源:igfitidea点击:

SecurityException with grantUriPermission when sharing a file with FileProvider

androidpermissionssecurityexceptionandroid-fileprovider

提问by DavidsAlias

I have two applications. I'm trying to share a file from application A to application B using a FileProvider. Application A calls the insert method on a ContentProvider in Application B to insert a record. The data inserted includes the Uri to the file I want to share from App A. The ContentProvider in App B would then try to read the shared file from App A. Since I'm not using an Intent to share the file, I'm calling Context.grantUriPermissionin App A to allow the read (and at times write):

我有两个应用程序。我正在尝试使用 FileProvider 将文件从应用程序 A 共享到应用程序 B。应用程序 A 调用应用程序 B 中的 ContentProvider 上的 insert 方法来插入一条记录。插入的数据包括我想从 App A 共享的文件的 Uri。然后 App B 中的 ContentProvider 会尝试从 App A 读取共享文件。由于我没有使用 Intent 来共享文件,因此我调用Context.grantUriPermissionApp A 以允许读取(有时写入):

mContext.grantUriPermission(MyPackageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

However, executing this line gives me (Names changed to protect the innocent):

然而,执行这一行给了我(为了保护无辜者而改变了名字):

java.lang.SecurityException: Uid 10066 does not have permission to uri content://au.com.example.AppA.fileprovider/MyFolder/MyFileName
at android.os.Parcel.readException(Parcel.java:1322)
at android.os.Parcel.readException(Parcel.java:1276)
at android.app.ActivityManagerProxy.grantUriPermission(ActivityManagerNative.java:2374)
at android.app.ContextImpl.grantUriPermission(ContextImpl.java:1371)
at android.content.ContextWrapper.grantUriPermission(ContextWrapper.java:400)
at etc...

App A has the following in the Manifest file:

App A 在 Manifest 文件中有以下内容:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="au.com.example.AppA.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true"
    android:readPermission="au.com.example.READ_CONTENT"
    android:writePermission="au.com.example.WRITE_CONTENT" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

filepaths.xml has:

filepaths.xml 有:

<paths>
    <files-path
        name="MyFolder"
        path="MyFolder/" />
</paths>

Both App A and App B have the following:

App A 和 App B 都具有以下功能:

<uses-permission android:name="au.com.example.READ_CONTENT" />
<uses-permission android:name="au.com.example.WRITE_CONTENT" />

I've tried defining the permissions in both apps. They are both signed with the same debug signature:

我试过在两个应用程序中定义权限。它们都使用相同的调试签名进行签名:

<permission
    android:name="au.com.example.READ_CONTENT"
    android:permissionGroup="MyGroup"
    android:protectionLevel="signature" >
</permission>
<permission
    android:name="au.com.example.WRITE_CONTENT"
    android:permissionGroup="MyGroup"
    android:protectionLevel="signature" >
</permission>

The actual path the file ends up in is:

文件最终的实际路径是:

/data/data/au.com.example.AppA/files/MyFolder

At this point I'm stumped. I don't know why I can't grant permission for a file I just created within the same application. So my questions are: Why am I getting this exception and how can I successfully grant permission to App B?

在这一点上,我被难住了。我不知道为什么我不能授予我刚刚在同一个应用程序中创建的文件的权限。所以我的问题是:为什么我会收到此异常以及如何成功授予 App B 权限?

回答by DavidsAlias

Well, after a week and a lot of trial and error, it seems the answer is to not specify permissions. So the App A Manifest should instead contain:

好吧,经过一周的反复试验,似乎答案是不指定权限。所以 App A Manifest 应该包含:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="au.com.example.AppA.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

ie, I removed the read and write permissions. My initial understanding, and failing to find documentation that said otherwise, was these were necessary to restrict access. However, I've found they actually interfere and cause Context.grantUriPermissionto fail. Access is limited already.

即,我删除了读写权限。我最初的理解是,并且未能找到另有说明的文档,这些是限制访问所必需的。但是,我发现它们实际上会干扰并导致Context.grantUriPermission失败。访问已经受到限制。

To complete the picture, and answer the second part of my question, I found the following:

为了完成图片并回答我问题的第二部分,我发现以下内容:

Android Permission denial in Widget RemoteViewsFactory for Content

Widget RemoteViewsFactory for Content 中的 Android 权限拒绝

I had to add:

我不得不补充:

final long token = Binder.clearCallingIdentity();
try {
    [retrieve file here]
} finally {
    Binder.restoreCallingIdentity(token);
}

to the Content Provider in App B. Otherwise it would get security errors as well.

到 App B 中的 Content Provider。否则它也会出现安全错误。

回答by srikanth kumar

The first problem in your code is exported attribute set to false. Please change it to true as,

代码中的第一个问题是导出属性设置为 false。请将其更改为 true,因为

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="au.com.example.AppA.fileprovider"
android:exported="true"
android:readPermission="au.com.example.READ_CONTENT"
android:writePermission="au.com.example.WRITE_CONTENT" >
</provider>

The second thing you have to do is, If external application App B is using content provider in App A.Then in App A manifest file mention permission as,

您必须做的第二件事是,如果外部应用程序 App B 正在使用 App A 中的内容提供程序。然后在 App A 清单文件中提及权限为,

<permission
android:name="au.com.example.READ_CONTENT"
 >
</permission>
<permission
android:name="au.com.example.WRITE_CONTENT"
 >
</permission>

and in App B mention uses-permission as,

在 App B 中提到使用权限,

<uses-permission android:name="au.com.example.READ_CONTENT" />
<uses-permission android:name="au.com.example.WRITE_CONTENT" />

Please let me know whether your problem has solved or not. If not please send your entire code. I will try to find the problem. Thank you.

请让我知道您的问题是否已解决。如果没有,请发送您的整个代码。我会努力找出问题所在。谢谢你。