Xamarin.Forms Android FileProvider: Java.Lang.NullPointerException при попытке прочитать файл - PullRequest
0 голосов
/ 11 ноября 2018

Я пытался сгенерировать файлы 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).

...