Estoy buscando una manera de compartir correctamente (no ABRIR) un archivo interno con una aplicación externa utilizando FileProvider de la biblioteca de soporte de Android .
Siguiendo el ejemplo en los documentos,
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.supportv4.my_files"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/my_paths" />
</provider>
y usar ShareCompat para compartir un archivo con otras aplicaciones de la siguiente manera:
ShareCompat.IntentBuilder.from(activity)
.setStream(uri) // uri from FileProvider
.setType("text/html")
.getIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
no funciona, ya que FLAG_GRANT_READ_URI_PERMISSION solo otorga permiso para el Uri especificado en data
la intención, no el valor del EXTRA_STREAM
extra (como fue establecido por setStream
).
Traté de comprometer la seguridad mediante el establecimiento android:exported
de true
para el proveedor, pero FileProvider
internamente comprueba si misma es exportada, cuando es así, se produce una excepción.
android
android-contentprovider
android-support-library
android-fileprovider
Randy Sugianto 'Yuku'
fuente
fuente
Respuestas:
Al usar la
FileProvider
biblioteca de soporte, debe otorgar y revocar manualmente permisos (en tiempo de ejecución) para que otras aplicaciones lean Uri específicos. Utilice los métodos Context.grantUriPermission y Context.revokeUriPermission .Por ejemplo:
Como último recurso, si no puede proporcionar el nombre del paquete, puede otorgar el permiso a todas las aplicaciones que puedan manejar una intención específica:
Método alternativo según la documentación :
Por cierto. si es necesario, puede copiar la fuente de FileProvider y cambiar el
attachInfo
método para evitar que el proveedor compruebe si se exporta.fuente
grantUriPermission
método, necesitamos proporcionar el nombre del paquete de la aplicación a la que queremos otorgar el permiso. Sin embargo, al compartir, generalmente no sabemos qué aplicación es el destino para compartir.Código de trabajo que muestra cómo compartir archivos desde la carpeta interna de la aplicación. Probado en Android 7 y Android 5.
AndroidManifest.xml
xml / provider_paths
Código en sí
fuente
ShareCompat.IntentBuilder
permiso URI de lectura y finalmente lo hizo por mí.FileProvider
que funciona. Las otras respuestas hacen que el manejo de la intención sea incorrecto (no lo usanShareCompat.IntentBuilder
), y esa aplicación no se puede abrir de ninguna manera significativa. Pasé literalmente la mayor parte del día en estas tonterías hasta que finalmente encontré tu respuesta.Esta solución funciona para mí desde OS 4.4. Para que funcione en todos los dispositivos, agregué una solución alternativa para dispositivos más antiguos. Esto asegura que siempre se use la solución más segura.
Manifest.xml:
file_paths.xml:
Java:
El permiso se revoca con revokeFileReadPermission () en los métodos onResume y onDestroy () del Fragmento o la Actividad.
fuente
file
eso no cambiará deonResume
aonDestroy
?Como, como dice Phil en su comentario sobre la pregunta original, esto es único y no hay otra información sobre SO en Google, pensé que también debería compartir mis resultados:
En mi aplicación, FileProvider funcionó para compartir archivos utilizando la intención de compartir. No hubo una configuración especial o código necesario, más allá de eso para configurar el FileProvider. En mi manifest.xml coloqué:
En my_paths.xml tengo:
En mi código tengo:
Y puedo compartir mi tienda de archivos en el almacenamiento privado de mis aplicaciones con aplicaciones como Gmail y Google Drive sin ningún problema.
fuente
Por lo que puedo decir, esto solo funcionará en las versiones más nuevas de Android, por lo que probablemente tendrá que encontrar una forma diferente de hacerlo. Esta solución funciona para mí en 4.4, pero no en 4.0 o 2.3.3, por lo que no será una forma útil de compartir contenido para una aplicación que debe ejecutarse en cualquier dispositivo Android.
En manifest.xml:
Tome nota cuidadosa de cómo especifica las autoridades. Debe especificar la actividad a partir de la cual creará el URI y lanzar la intención de compartir, en este caso la actividad se llama SharingActivity. ¡Este requisito no es obvio en los documentos de Google!
file_paths.xml:
Tenga cuidado al especificar la ruta. El valor predeterminado anterior es la raíz de su almacenamiento interno privado.
En SharingActivity.java:
En este ejemplo estamos compartiendo una imagen JPEG.
Finalmente, probablemente sea una buena idea asegurarse de que ha guardado el archivo correctamente y que puede acceder a él con algo como esto:
fuente
En mi aplicación FileProvider funciona bien, y puedo adjuntar archivos internos almacenados en el directorio de archivos a clientes de correo electrónico como Gmail, Yahoo, etc.
En mi manifiesto como se menciona en la documentación de Android, coloqué:
Y como mis archivos se almacenaron en el directorio de archivos raíz, los filepaths.xml fueron los siguientes:
Ahora en el código:
Esto funcionó para mí. Espero que esto ayude :)
fuente
Si obtiene una imagen de la cámara, ninguna de estas soluciones funciona para Android 4.4. En este caso, es mejor verificar las versiones.
fuente
solo para mejorar la respuesta dada anteriormente: si obtiene NullPointerEx:
También puede usar getApplicationContext () sin contexto
fuente
Quiero compartir algo que nos bloqueó durante un par de días: el código del proveedor de archivos DEBE insertarse entre las etiquetas de la aplicación, no después. Puede ser trivial, pero nunca se especifica, ¡y pensé que podría haber ayudado a alguien! (gracias de nuevo a piolo94)
fuente