Я пытался сгенерировать файлы Word и открыть его на Android с помощью Xamarin.Forms. Я могу создать файл, но при попытке прочитать следующую ошибку выдает:
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
Код, который я использую, выглядит следующим образом:
AndroidManifest.xml содержит:
<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>
Поставщик provider_paths.xml, находящийся в папке Resources / xml, имеет вид:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="/Atas"/>
<files-path name="files" path="/Atas"/>
</paths>
Асинхронный метод для сохранения файла и открытия:
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);
}
}
Я боролся с этим кодом. Многие потоки рассказывали о проблеме на сайте provider_paths.xml, но я не могу понять, почему, где и даже если она действительно есть.
РЕДАКТИРОВАТЬ .: для более ясного воспроизведения проблемы я загрузил образец на свой GitHub здесь: https://github.com/RaelsonCraftz/XamarinFileProviderSample
Также небольшое обновление. Если вы установите для Targed Android version
значение Use Compile using SDK version
, приложению удастся хотя бы создать файл, но он не откроется, предоставив исключение Java.Lang.NullPointerException, упомянутое выше. Если вы установите Android 8.1 (API Level 27 - Oreo), ему не удастся создать файл. Это говорит о том, что разрешение не было предоставлено на этой линии exception = e.ToString();
. Я отметил линию, где это происходит, это на public async Task Save(string fileName, string contentType, MemoryStream stream)
.