SecurityException con grantUriPermission al compartir un archivo con FileProvider

Tengo dos aplicaciones. Estoy intentando compartir un archivo de la aplicación A a la aplicación B usando un FileProvider. La aplicación A llama al método insert en un ContentProvider en la Aplicación B para insertar un registro. Los datos insertados incluyen el Uri al archivo que quiero compartir desde la aplicación A. El ContentProvider en la aplicación B intentaría leer el archivo compartido de la aplicación A. Como no estoy usando una intención de compartir el archivo, Llamando Context.grantUriPermission en la aplicación A para permitir la lectura (ya veces escribir):

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

Sin embargo, ejecutar esta línea me da (Nombres cambiados para proteger a los inocentes):

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

La aplicación A tiene lo siguiente en el archivo 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 tiene:

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

Tanto la aplicación A como la aplicación B tienen lo siguiente:

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

He intentado definir los permisos en ambas aplicaciones. Ambos están firmados con la misma firma de depuración:

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

La ruta actual en la que termina el archivo es:

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

En este punto estoy perplejo. No sé por qué no puedo otorgar permiso para un archivo que acabo de crear dentro de la misma aplicación. Así que mis preguntas son: ¿Por qué recibo esta excepción y cómo puedo conceder permiso a la aplicación B?

Bueno, después de una semana y un montón de ensayo y error, parece que la respuesta es no especificar los permisos. Por lo tanto, la aplicación de un manifiesto debe contener:

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

Es decir, eliminé los permisos de lectura y escritura. Mi entendimiento inicial, y al no encontrar documentación que dijera lo contrario, era que éstos eran necesarios para restringir el acceso. Sin embargo, he encontrado que realmente interfieren y causan Context.grantUriPermission fallar. El acceso ya está limitado.

Para completar la imagen, y responder a la segunda parte de mi pregunta, encontré lo siguiente:

Negación de permisos de Android en Widget RemoteViewsFactory para contenido

Tuve que añadir:

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

Al proveedor de contenido en la aplicación B. De lo contrario, obtendría errores de seguridad también.

El primer problema en su código es el atributo export set a false. Por favor, cambie a true como,

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

La segunda cosa que usted tiene que hacer es, si la aplicación externa App B está utilizando el abastecedor de contenido en la aplicación A. Entonces en App un archivo manifiesto menciona permiso como,

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

Y en la aplicación B mencionar usa-permiso como,

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

Por favor, hágamelo saber si su problema ha resuelto o no. Si no, envíe su código completo. Voy a tratar de encontrar el problema. Gracias.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.