13

我有两个应用程序。我试图使用FileProvider将文件从应用程序A共享到应用程序B.应用程序A在应用程序B中的ContentProvider上调用insert方法插入记录。插入的数据包括Uri到我想要从App A共享的文件.App B中的ContentProvider然后尝试从App A读取共享文件。 因为我没有使用Intent来共享文件, M在应用主叫Context.grantUriPermission允许读取(有时写):与FileProvider共享文件时发生的带有grantUriPermission的SecurityException

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

但是,在执行此行给我(名称变更为保护无辜者):

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... 

应用程序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有:

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

两个应用程序A和应用B有以下几点:

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

我试图定义在这两个应用程序的权限。它们都具有相同的调试签名签名:

<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> 

在文件中最终的实际路径是:

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

在这一点上我很为难。我不知道为什么我无法授予我在同一个应用程序中创建的文件的权限。所以我的问题是:为什么我得到这个异常,我怎样才能成功授予应用程序B的权限?

回答

15

那么,经过一个星期和大量的试验和错误,似乎答案是不指定权限。因此,应用程序清单应该包含:

<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> 

即,我删除了读写权限。我最初的理解,并没有找到其他文件,这是必要的限制访问。但是,我发现它们实际上会干扰并导致Context.grantUriPermission失败。访问权限已被限制。

要完成的图片,并回答我的问题的第二部分,我发现:

Android Permission denial in Widget RemoteViewsFactory for Content

我不得不添加:

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

在应用中的内容提供商B.否则它也会得到安全错误。

+0

我也有这个问题,并从清单中删除读取权限,但仍然得到'由java.lang.SecurityException:权限拒绝:打开提供程序android.support.v4.content.FileProvider ProcessRecord {40b7b968 7764: com.google.android.gm/10018}(pid = 7764,uid = 10018)需要null或null – StuStirling

+0

@ DiscoS2我见过同样的事情。我发现卸载并重新安装该应用程序修复了它。我没有检查过,但我怀疑是否有某种缓存清单正在进行。 – DavidsAlias

+2

如果您没有使用Signature级别的权限,您的应用程序是否暴露在外部威胁之下才能读取任何具有正确Uri的文件? – Toochka

-2

代码中的第一个问题是导出的属性设置为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> 

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

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

和应用B提及使用许可权的,

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

请让我知道你的问题是否已经解决或没有。如果不是,请发送您的整个代码。我会尽力找到问题。 谢谢。

+1

我最终解决了这个问题。请参阅接受的答案。 Exported = true将允许访问具有列出权限的任何应用程序。我试图将应用程序分享给另一个应用程序,而不是任何应用程序。 – DavidsAlias

+0

你的意思是临时权限 –

+3

'FileProvider'检查'android:exported =“true”'并且会抛出异常。 – WindRider