【问题标题】:How do I download a file on both Android X and iOS that is publicly available, using Xamarin.Forms?如何使用 Xamarin.Forms 在 Android X 和 iOS 上下载公开可用的文件?
【发布时间】:2020-07-10 17:01:55
【问题描述】:

查看此问题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() 

使用以下代码。

    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);
    }

通过answer,我创建了一个 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

我还没有找到任何方法来获取带有 Xamarin.Forms 的 Android 10 的公共路径。我查看了Android Docs for Content providers,但它是用 Java 编写的,我还不能让它在 C# 中运行。

任何帮助将不胜感激。

【问题讨论】:

  • 您可以使用 FileProvider 以通常的方式解决 FileUriExposedException。
  • 在 Android Q 下无法再访问外部存储。但您可以编辑清单文件以获得访问权限。

标签: android ios xamarin.forms download android-10.0


【解决方案1】:

我确实找到了Solution

找到了解决办法

安卓版

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 上那样直接与其他应用共享文件。沙盒对安全性有好处,但在这种情况下,他们如何实现它,它限制了选项。两个应用程序都必须预先注册/预先分配在“应用程序组”中才能直接共享文件。请参阅此ArticleApple Docs 了解更多信息。

【讨论】:

    猜你喜欢
    • 2019-02-19
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 2021-04-23
    • 2017-10-16
    • 2017-02-21
    • 2011-11-12
    • 2019-09-19
    相关资源
    最近更新 更多