Je cherche un moyen de partager correctement (et non OPEN) un fichier interne avec une application externe à l'aide de FileProvider de la bibliothèque de support Android .
En suivant l'exemple sur la documentation,
<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>
et en utilisant ShareCompat pour partager un fichier avec d'autres applications comme suit:
ShareCompat.IntentBuilder.from(activity)
.setStream(uri) // uri from FileProvider
.setType("text/html")
.getIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
ne fonctionne pas, puisque FLAG_GRANT_READ_URI_PERMISSION n'accorde la permission que pour l'URI spécifié sur l'intent data
, pas la valeur de l' EXTRA_STREAM
extra (comme a été défini par setStream
).
J'ai essayé de compromettre la sécurité en définissant android:exported
sur true
pour le fournisseur, mais FileProvider
vérifie en interne si lui-même est exporté, quand c'est le cas, il lève une exception.
android
android-contentprovider
android-support-library
android-fileprovider
Randy Sugianto 'Yuku'
la source
la source
Réponses:
À l'aide
FileProvider
de la bibliothèque de support, vous devez accorder et révoquer manuellement les autorisations (au moment de l'exécution) pour que d'autres applications lisent des Uri spécifiques. Utilisez les méthodes Context.grantUriPermission et Context.revokeUriPermission .Par exemple:
En dernier recours, si vous ne pouvez pas fournir de nom de package, vous pouvez accorder l'autorisation à toutes les applications qui peuvent gérer une intention spécifique:
Méthode alternative selon la documentation :
Btw. si vous en avez besoin, vous pouvez copier la source de FileProvider et changer de
attachInfo
méthode pour empêcher le fournisseur de vérifier s'il est exporté.la source
grantUriPermission
méthode, nous devons fournir le nom du package de l'application à laquelle nous voulons accorder l'autorisation. Cependant, lors du partage, nous ne savons généralement pas quelle application est la destination de partage.Exemple de code entièrement fonctionnel pour partager un fichier à partir du dossier d'application interne. Testé sur Android 7 et Android 5.
AndroidManifest.xml
xml / chemin_fournisseur
Code lui-même
la source
ShareCompat.IntentBuilder
autorisation de lecture et d'URI l'a finalement fait pour moi.FileProvider
qui fonctionne. Les autres réponses ont une mauvaise gestion de l'intention (elles ne l'utilisent pasShareCompat.IntentBuilder
), et cette intention ne peut pas être ouverte par des applications externes de manière significative. J'ai passé littéralement la majeure partie de la journée sur ce non-sens jusqu'à ce que finalement trouvé votre réponse.Cette solution fonctionne pour moi depuis OS 4.4. Pour le faire fonctionner sur tous les appareils, j'ai ajouté une solution de contournement pour les appareils plus anciens. Cela garantit que la solution la plus sûre est toujours utilisée.
Manifest.xml:
file_paths.xml:
Java:
L'autorisation est révoquée avec revokeFileReadPermission () dans les méthodes onResume et onDestroy () du fragment ou de l'activité.
la source
file
cela ne changera pas deonResume
àonDestroy
?Comme Phil le dit dans son commentaire sur la question initiale, c'est unique et il n'y a pas d'autre information sur SO sur Google, j'ai pensé que je devrais également partager mes résultats:
Dans mon application, FileProvider a fonctionné dès le départ pour partager des fichiers en utilisant l'intention de partage. Il n'y avait aucune configuration ou code spécial nécessaire, à part cela pour configurer le FileProvider. Dans mon manifest.xml j'ai placé:
Dans my_paths.xml, j'ai:
Dans mon code j'ai:
Et je suis en mesure de partager mon stockage de fichiers dans le stockage privé de mes applications avec des applications telles que Gmail et Google Drive sans aucun problème.
la source
Pour autant que je sache, cela ne fonctionnera que sur les nouvelles versions d'Android, vous devrez donc probablement trouver une façon différente de le faire. Cette solution fonctionne pour moi sur 4.4, mais pas sur 4.0 ou 2.3.3, donc ce ne sera pas un moyen utile de partager du contenu pour une application destinée à fonctionner sur n'importe quel appareil Android.
Dans manifest.xml:
Prenez bien note de la manière dont vous spécifiez les autorités. Vous devez spécifier l'activité à partir de laquelle vous allez créer l'URI et lancer l'intention de partage. Dans ce cas, l'activité s'appelle SharingActivity. Cette exigence n'est pas évidente dans la documentation de Google!
file_paths.xml:
Faites attention à la manière dont vous spécifiez le chemin. Ce qui précède correspond par défaut à la racine de votre stockage interne privé.
Dans SharingActivity.java:
Dans cet exemple, nous partageons une image JPEG.
Enfin, c'est probablement une bonne idée de vous assurer que vous avez correctement enregistré le fichier et que vous pouvez y accéder avec quelque chose comme ceci:
la source
Dans mon application, FileProvider fonctionne très bien, et je suis capable de joindre des fichiers internes stockés dans le répertoire de fichiers à des clients de messagerie tels que Gmail, Yahoo, etc.
Dans mon manifeste comme mentionné dans la documentation Android, j'ai placé:
Et comme mes fichiers étaient stockés dans le répertoire racine des fichiers, les chemins de fichiers.xml étaient les suivants:
Maintenant dans le code:
Cela a fonctionné pour moi, j'espère que cela aide :)
la source
Si vous obtenez une image de la caméra, aucune de ces solutions ne fonctionne pour Android 4.4. Dans ce cas, il est préférable de vérifier les versions.
la source
juste pour améliorer la réponse donnée ci-dessus: si vous obtenez NullPointerEx:
vous pouvez également utiliser getApplicationContext () sans contexte
la source
Je veux partager quelque chose qui nous a bloqués pendant quelques jours: le code du fournisseur de fichiers DOIT être inséré entre les balises d'application, pas après. C'est peut-être trivial, mais ce n'est jamais spécifié, et je pensais que j'aurais pu aider quelqu'un! (merci encore à piolo94)
la source