Xamarin.Forms Android FileProvider: GrantWriteUriPermission не всегда работает

Я хочу редактировать файлы из внутреннего хранилища моего приложения Xamarin.Forms для Android в сторонних приложениях, например заполнять элементы формы в файле PDF или редактировать файл .docx.

В моей реализации файл правильно открывается во внешнем приложении, но в некоторых приложениях он открывается только для чтения. Adobe Acrobat и Microsoft Word открывают файлы только для чтения, в то время как другие приложения, такие как Google Docs, могут выполнять обратную запись в файл. (Я использую Microsoft Word с действующей подпиской на Office365).

Мой FileProvider в AndroidManifest.xml:

<provider android:name="android.support.v4.content.FileProvider" 
          android:authorities="xamarintestapp.xamarintestapp.fileprovider" 
          android:grantUriPermissions="true" 
          android:exported="false">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS"     
               android:resource="@xml/filepaths" />
</provider>

пути к файлам.xml:

<paths>
        <files-path name="files" path="."/>
</paths>

Через Xamarin.Forms DependencyService я запускаю действие и передаю содержимое uri для запуска внешнего приложения:

public void OpenFile(string fileName)
{
    string auth = "xamarintestapp.xamarintestapp.fileprovider";
    string mimeType = Android.Webkit.MimeTypeMap.Singleton.GetMimeTypeFromExtension(Android.Webkit.MimeTypeMap.GetFileExtensionFromUrl(fileName.ToLower()));
    if (mimeType == null)
        mimeType = "*/*";

    var file = new Java.IO.File(Path.Combine(Forms.Context.FilesDir.Path, fileName));
    Android.Net.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);

    // Trying to allow writing to the external app ...
    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);
}

Я что-то не так делаю или это просто невозможно?


person stefffdev    schedule 15.02.2017    source источник
comment
Если одно приложение ведет себя так, как ожидалось, а два нет, то почему вы думаете, что виноваты вы? Попробуйте другие расширения и другие приложения. Попробуйте эти два приложения без поставщика файлов.   -  person greenapps    schedule 15.02.2017
comment
Я пробовал оба приложения без FileProvider (копируя файлы во внешнее хранилище и открывая их оттуда - тогда файлы открываются для записи). Я также пробовал ContentProvider и DocumentProvider, с тем же результатом, некоторые приложения открывают файлы только для чтения, а другие нет, мне любопытно, почему...   -  person stefffdev    schedule 15.02.2017
comment
Основываясь на вашем коде, таком как Forms.Context.StartActivity(intent);, вы на самом деле разрабатываете решение Xamarin.Forms, а не Xamarin.Android, я прав? И ваша проблема связана с разрешением на запись на других платформах, таких как UWP, а не на платформе Android?   -  person Grace Feng    schedule 16.02.2017
comment
Спасибо за ваш ответ, вы правы, я разрабатываю приложение Xamarin.Forms и реализую метод OpenFile в проектах для конкретной платформы через Xamarin.Forms DependencyService. Я обновил свой вопрос соответственно. Моя реализация OpenFile под UWP работает, но у меня проблемы с Android, я еще не пробовал iOS.   -  person stefffdev    schedule 16.02.2017


Ответы (1)


После дальнейшего расследования я могу подтвердить, что проблема связана с тем, что приложение получает мое намерение (например, Microsoft Word).

Когда я запускаю намерение EDIT вместо намерения VIEW, как в

Intent intent = new Intent(Intent.ActionEdit);

файл открывается с доступом для записи в определенных приложениях (xodo pdf, google docs), но доступен только для чтения в других приложениях (Adobe PDF Reader, Microsoft Word), поэтому я предполагаю, что эти приложения неправильно реализуют получение намерения редактирования.

person stefffdev    schedule 20.03.2017