Ajith
Ajith

Reputation: 55

File Download in Xamarin forms

In Xamarin.Forms project, I'm trying to download the file from the blob storage, also I need to save it in a device local folder and need to open it immediately.

I'm getting this exception while opening the file Fil:///LocalFolderUrlOfTheFile exposed beyond app through Intent.getData()

I'm getting this exception only in android versions which are greater than Marshmallow.

Here are codes which i'm using to opening the file:

public void SaveandOpenFile(byte[] data, string fileName)
    {
        string externalStorageState = global::Android.OS.Environment.ExternalStorageState;
        var externalPath = global::Android.OS.Environment.ExternalStorageDirectory.Path + "/" + global::Android.OS.Environment.DirectoryDownloads + "/" + fileName;
        File.WriteAllBytes(externalPath, data);

        Java.IO.File file = new Java.IO.File(externalPath);
        file.SetReadable(true);

        string application = "";
        string extension = Path.GetExtension(externalPath);

        // get mimeTye
        switch (extension.ToLower())
        {
            case ".txt":
                application = "text/plain";
                break;
            case ".doc":
            case ".docx":
                application = "application/msword";
                break;
            case ".pdf":
                application = "application/pdf";
                break;
            case ".xls":
            case ".xlsx":
                application = "application/vnd.ms-excel";
                break;
            case ".jpg":
            case ".jpeg":
            case ".png":
                application = "image/jpeg";
                break;
            default:
                application = "*/*";
                break;
        }

        //Android.Net.Uri uri = Android.Net.Uri.Parse("file://" + filePath);
        Android.Net.Uri uri = Android.Net.Uri.FromFile(file);
        Intent intent = new Intent(Intent.ActionView);
        intent.SetDataAndType(uri, application);
        intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);

        Forms.Context.StartActivity(intent);
    }

Please let me know if i'm missing something. Thanks in advance!

Upvotes: 1

Views: 2527

Answers (1)

NKR
NKR

Reputation: 2943

You can't expose the File outside of your app in new versions. You should setup couple of things to do that. Follow these steps:

Step 1: Goto your android's manifest file and define file providers inside application tags.

<provider android:name="android.support.v4.content.FileProvider" 
android:authorities="${applicationId}.provider" android:exported="false" 
android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider>

Step 2: Define the Provider path in XML

  1. Create XML folder if not exists inside your Resources folder.
  2. Create an XML file (If you followed previous step exactly then name of that file would be "provider_paths.xml"

Step 3: Define the Provider file path in Provider Path XML file you created in Step 2

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="files" path="."/>
    <internal-path name="files" path="."/>
    <files-path name="files" path="."/>
</paths>

Step 4: When you download your file you should save them in location that you defined in Step 3. I save the file in android at root directory below:

root = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

Step 5: Opening the File, Following is the method that I'm using to share. Hope you understand and make changes on yours accordingly :

    public Task Share(string title, string message, string filePath)
    {
        var extension = filePath.Substring(filePath.LastIndexOf(".",StringComparison.InvariantCultureIgnoreCase) + 1).ToLower();
        var contentType = string.Empty;

        Java.IO.File file=new  Java.IO.File(filePath);
        var apkURI = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName+ ".provider", file);

        switch (extension)
        {
            case "pdf":
                contentType = "application/pdf";
                break;
            case "png":
                contentType = "image/png";
                break;
            default:
                contentType = "application/octetstream";
                break;
        }

        var intent = new Intent(Intent.ActionSend);

        intent.SetFlags(ActivityFlags.GrantReadUriPermission);

        intent.SetType(contentType);
        intent.PutExtra(Intent.ExtraStream, apkURI);
        intent.PutExtra(Intent.ExtraText, string.Empty);
        intent.PutExtra(Intent.ExtraSubject, message ?? string.Empty);


        var chooserIntent = Intent.CreateChooser(intent, title ?? string.Empty);
        chooserIntent.SetFlags(ActivityFlags.ClearTop);
        chooserIntent.SetFlags(ActivityFlags.NewTask);

        context.StartActivity(chooserIntent);

        return Task.FromResult(true);
    }

Let me know if you need any help.

Upvotes: 1

Related Questions