I've been trying generate word files and open it on an Android using Xamarin.Forms. I can create the file, but the following error is thrown when I try to read:
Java.Lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
The code I'm using is as follows:
The AndroidManifest.xml contains:
<application>
<provider android:name="android.support.v4.content.FileProvider"
android:authorities="com.ESFJP.ESFAtas.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/>
</provider>
</application>
The provider_paths.xml, which lies in the folder Resources/xml, is:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="/Atas"/>
<files-path name="files" path="/Atas"/>
</paths>
The async method to save the file and open:
public async Task Save(string fileName, string contentType, MemoryStream stream)
{
string exception = string.Empty;
string root = null;
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
Java.IO.File myDir = new Java.IO.File(root + "/Atas");
myDir.Mkdir();
Java.IO.File file = new Java.IO.File(myDir, fileName);
if (file.Exists()) file.Delete();
try
{
//The permission failure happens in this line when the target version is set to API Level 27 Nougat
FileOutputStream outs = new FileOutputStream(file);
stream.Position = 0;
outs.Write(stream.ToArray());
outs.Flush();
outs.Close();
}
catch (Exception e)
{
//The permission failure can be seen here if the target version is set to API level 27 Nougat
exception = e.ToString();
}
finally
{
stream.Dispose();
}
if (file.Exists())
{
string auth = "com.ESFJP.ESFAtas.fileprovider";
string extension = Android.Webkit.MimeTypeMap.GetFileExtensionFromUrl(Uri.FromFile(file).ToString());
string mimeType = Android.Webkit.MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
if (mimeType == null)
mimeType = "*/*";
//The Java.Lang.NullPointerException is thrown from this line \/\/\/
Uri uri = FileProvider.GetUriForFile(Forms.Context, auth, file);
Intent intent = new Intent(Intent.ActionView);
intent.SetDataAndType(uri, mimeType);
intent.AddFlags(ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission);
intent.AddFlags(ActivityFlags.NewTask | ActivityFlags.NoHistory);
var resInfoList = Forms.Context.PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
foreach (var resolveInfo in resInfoList)
{
var packageName = resolveInfo.ActivityInfo.PackageName;
Forms.Context.GrantUriPermission(packageName, uri, ActivityFlags.GrantWriteUriPermission | ActivityFlags.GrantPrefixUriPermission | ActivityFlags.GrantReadUriPermission);
}
Forms.Context.StartActivity(intent);
}
}
I've been struggling with this code. Many threads told about the issue being on the provider_paths.xml, but I can't figure out why or where or even if it's actually there.
Also, a small note. If you set the Targed Android version to Use Compile using SDK version the app manages to at least create the file, but it won't open, giving the Java.Lang.NullPointerException mentioned above. IF you set it to Android 8.1 (API Level 27 - Oreo), it won't manage to create the file. It says that the permission has not been granted at this line exception = e.ToString();. I've marked the line where that happens, it's on the public async Task Save(string fileName, string contentType, MemoryStream stream).
I created a sample in my GitHub where this issue happens: https://github.com/RaelsonCraftz/XamarinFileProviderSample. Any help is appreciated!