Как загрузить общедоступный файл на Android X и iOS с помощью Xamarin.Forms? - PullRequest
0 голосов
/ 10 июля 2020

Рассматривая эту проблему xamarin / Essentials # 1322 , как мне загрузить файл как на Android (версии 6-10, Api 23-29), так и на iOS (версия 13.1+) который является общедоступным (может быть предоставлен другим приложениям, например Microsoft Word). Мне не нужно предоставлять доступ на запись другим приложениям, достаточно только чтения, если его необходимо ограничить.

Я получаю следующее исключение:

    [Bug] Android.OS.FileUriExposedException: file:///data/user/0/{AppBundleName}/cache/file.doc exposed beyond app through Intent.getData() 

со следующим code.

    public static string GetCacheDataPath( string fileName ) => Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fileName);
    public static FileInfo SaveFile( string filename, Uri link )
    {
        using var client = new WebClient();
        string path = GetCacheDataPath(filename);
        DebugTools.PrintMessage(path);
        client.DownloadFile(link, path);
        return new FileInfo(path);
    }
    public async Task Test(Uri link)
    {
        LocalFile path = await SaveFile("file.doc", link).ConfigureAwait(true);
        var url = new Uri($"ms-word://{path.FullName}", UriKind.Absolute);
        await Xamarin.Essentials.Launcher.OpenAsync(url).ConfigureAwait(true);
    }

С этим ответом я создал интерфейс FileService, и он работает с локальными частными файлами, но я не могу поделиться файлами. Начиная с Android Q (10 / Api 29), следующее устарело.

    string path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;  // deprecated

Я получаю следующее исключение:

System.UnauthorizedAccessException: Access to the path '/storage/emulated/0/Download/file.doc' is denied. ---> System.IO.IOException: Permission denied

Я еще не нашел способа чтобы получить путь publi c для Android 10 с помощью Xamarin.Forms. Я просмотрел Android Документы для поставщиков контента , но он находится в Java, и я пока не могу заставить его работать в C#.

Любая помощь будет очень признателен.

1 Ответ

0 голосов
/ 29 июля 2020

Я нашел Решение

Нашел исправление

Для Android

public Task<System.IO.FileInfo> DownloadFile( Uri link, string fileName )
{
  if ( link is null )
      throw new ArgumentNullException(nameof(link));

  using System.Net.WebClient client = new System.Net.WebClient();

  // MainActivity is the class that loads the application.
  // MainActivity.Instance is a property that you set "Instance = this;" inside of OnCreate.
  Java.IO.File root = MainActivity.Instance.GetExternalFilesDir(MediaStore.Downloads.ContentType);
  string path     = Path.Combine(root.AbsolutePath, fileName);

  client.DownloadFile(link, path);

  return Task.FromResult(new System.IO.FileInfo(path));
} 
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
  internal static MainActivity Instance { get; private set; }
  
  protected override void OnCreate(Bundle savedInstanceState)
  {
      ...
      Instance = this;
      ...
  }
  ...
}

Для iOS

public Task<System.IO.FileInfo> DownloadFile( Uri link, string fileName )
{
  if ( link is null )
      throw new ArgumentNullException(nameof(link));

  using System.Net.WebClient client = new System.Net.WebClient();
  string path = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fileName)
  client.DownloadFile(link, path);

  return Task.FromResult(new System.IO.FileInfo(path));
} 
public async Task Share()
{
  // back in shared project, choose a file name and pass the link.
  System.IO.FileInfo info = await DependencyService.Get<IDownload>().DownloadFile(new Uri("<enter site>", "file.doc").ConfigureAwait(true);
  
  ShareFile shareFile = new ShareFile(info.FullName, "doc"); // enter the file type / extension.
  var request = new ShareFileRequest("Choose the App to open the file", shareFile);
  await Xamarin.Essentials.Share.RequestAsync(request).ConfigureAwait(true);
}

Обратите внимание, что для iOS, из-за бесконечной мудрости Apple ... Я не могу поделиться файлом напрямую с другим приложением, как я могу на Android. Песочница хороша для безопасности, но в данном случае, как они ее реализовали, ограничивает возможности. Оба приложения должны быть предварительно зарегистрированы / заранее выделены в «Группе приложений» для прямого обмена файлами. См. Эту статью и Apple Docs для получения дополнительной информации.

...