简体   繁体   中英

How do I download a file on both Android X and iOS that is publicly available, using Xamarin.Forms?

Looking at this issue xamarin/Essentials#1322 , how do I download a file on both Android ( versions 6-10, Api 23-29 ) and iOS ( version 13.1+ ) that is publicly available (share-able to other apps, such as Microsoft Word). I don't need to give write access to the other apps, just read-only is ok if it must be restricted.

I get the following exception:

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

With the following 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);
    }

With this answer , I created a FileService interface and it works with local private files but I am unable to share the files. Starting with Android Q (10 / Api 29), the following is deprecated.

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

I get the following exception:

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

I haven't found any way yet to get a public path for Android 10 with Xamarin.Forms. I've looked at the Android Docs for Content providers but it's in Java, and I can't get it working in C# yet.

Any help would be greatly appreciated.

I did find a Solution

Found a fix

For 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; ... }... }

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

Note that for iOS, due to Apple's infinite wisdom... I cannot share the file directly with another app as I can on Android. Sandboxing is good for security but in this case, how they implemented it, it limits options. Both Applications must be pre-registered / pre-allocated in an "App Group" to share files directly. See this Article and the Apple Docs for more information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM