J'ai suivi l'exemple de code sur le référence développeur Android sur FileProviders mais cela ne fonctionnera pas.
J'ai configuré le chemin files/exports/
Dans la définition du fournisseur de fichiers dans mon manifeste et les fichiers référencés existent sur ce chemin.
Dans mon manifeste:
<provider Android:name="Android.support.v4.content.FileProvider" Android:authorities="com.company.app.fileprovider" Android:exported="false" Android:grantUriPermissions="true">
<meta-data Android:name="Android.support.FILE_PROVIDER_PATHS" Android:resource="@xml/file_paths" />
</provider>
Et dans xml/file_paths.xml
<?xml version="1.0" encoding="UTF-8" ?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<files-path name="exports" path="exports/"/>
</paths>
Ensuite, j'essaye d'obtenir le content-uri avec le code suivant:
Java.IO.File exportFile =
new Java.IO.File ("/data/data/com.company.app/files/exports/file.pdf");
Android.Net.Uri exportUri =
Android.Support.V4.Content.FileProvider.GetUriForFile (this, "com.company.app.fileprovider", exportFile);
Cependant, j'obtiens cette erreur:
Exception of type 'Java.Lang.NullPointerException' was thrown.
at Android.Runtime.JNIEnv.CallStaticObjectMethod (IntPtr jclass, IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00064] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.2-branch/4b53fbd0/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:1160
at Android.Support.V4.Content.FileProvider.GetUriForFile (Android.Content.Context context, System.String authority, Java.IO.File file) [0x00000] in <filename unknown>:0
at com.company.App.ImageAndSubtitle.cloudStorageDidDownloadFile (System.Object sender, com.company.App.CloudStorageEventArgs args) [0x001f7] in /app_path/Screens/ImageAndSubtitle.cs:187
--- End of managed exception stack trace ---
Java.lang.NullPointerException
at Android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.Java:243)
at Android.support.v4.content.FileProvider.getPathStrategy(FileProvider.Java:217)
at Android.support.v4.content.FileProvider.getUriForFile(FileProvider.Java:130)
at mono.Java.lang.RunnableImplementor.n_run(Native Method)
at mono.Java.lang.RunnableImplementor.run(RunnableImplementor.Java:29)
at Android.os.Handler.handleCallback(Handler.Java:615)
at Android.os.Handler.dispatchMessage(Handler.Java:92)
at Android.os.Looper.loop(Looper.Java:137)
at Android.app.ActivityThread.main(ActivityThread.Java:4838)
at Java.lang.reflect.Method.invokeNative(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:511)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:875)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:642)
at dalvik.system.NativeStart.main(Native Method)
Mise à jour
À partir du code source Android, je pourrais le rechercher dans la mesure où je sais maintenant que cette commande dans Android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.Java:243)
échouera et retournera null
:
final ProviderInfo info = context.getPackageManager().resolveContentProvider(authority, PackageManager.GET_META_DATA);
Mais je ne sais pas pourquoi ...
J'ai finalement trouvé un bon exemple de code sur la façon de créer ContentProviders et FileProviders sur https://github.com/commonsguy/cw-omnibus/tree/master/ContentProvider
L'erreur réelle dans mon code était que dans le fichier Manifest j'avais la balise provider
à l'extérieur de la balise application
, mais elle doit être à l'intérieur. Le manifeste doit ressembler à ceci:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:versionCode="1" Android:versionName="1.0" package="com.company.app">
<uses-sdk Android:minSdkVersion="13" />
<permission
Android:name="com.company.app.fileprovider.READ"
Android:description="@string/perm_read"
Android:label="@string/perm_read_label"/>
<uses-permission Android:name="com.company.app.fileprovider.READ"/>
<application Android:label="MyApp">
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="com.company.app.fileprovider"
Android:exported="false"
Android:grantUriPermissions="true"
Android:readPermission="com.company.app.fileprovider.READ">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/file_paths" />
</provider>
</application>
<uses-permission Android:name="Android.permission.INTERNET" />
</manifest>
En essayant de configurer un FileProvider pour obtenir un fichier PDF qui se trouve sur l'appareil et pouvoir l'envoyer par e-mail, j'ai également rencontré cette exception. En lisant les différentes réponses - il semble un peu compliqué de configurer correctement le FileProvider à la main (au moins cette première fois).
Enfin, ce qui a fonctionné pour moi a été de copier les composants de cet exemple dans un nouveau projet vide: https://github.com/IanDarwin/Android-Cookbook-Examples/tree/master/PdfShare
Une fois que je le vois fonctionner de manière autonome, je peux apporter les modifications à mon projet actuel.
Plus précisément, voici les fichiers à répliquer:
1. AndroidManifest.xml - où se trouve toute la configuration FileProvider délicate
2. file_paths.xml - Il s'agit d'un petit mais important composant. En regardant SO il y a une variété de réponses pour ce qu'il faut y mettre, mais c'est seulement à partir de ce projet que l'installation a fonctionné pour moi
3. MainActivity.Java - la configuration Java correspondante pour fonctionner avec ce qui est configuré dans le manifeste; et bien sûr, n'oubliez pas le fichier de mise en page associé
Cette erreur s'est produite dans mon cas car j'avais transmis un nom de package incorrect au deuxième paramètre de GetUriForFile
. J'ai utilisé BuildConfig.PACKAGE_NAME
qui s'est résolu en Android.support.multidex qui est incorrect.