Why cannot I attach a file in Android N+?

FedericoNavarreteFedericoNavarrete SVMember ✭✭
edited December 2018 in Xamarin.Android

I'm developing an App that is exporting some HTML tables as attachments. I have noticed that my code doesn't work if I try to attach the html table to Gmail, Google Drive or any E-mail provider in Android N+, but it can upload the file to OneDrive, WhatsApp, Skype, etc. Without any issue.

This is my current code:

Intent share = new Intent(Intent.ActionSend);
share.SetType("text/html");
share.AddFlags(ActivityFlags.NewDocument);

var file = CreateDirFile($"Meeting_{DateTime.Now.ToString("dd_MM_yyyy_HH_mm_ss")}.html");

try
{
    FileOutputStream fout = new FileOutputStream(file);
    fout.Write(System.Text.Encoding.ASCII.GetBytes($"<!DOCTYPE html><html><body><table><tr><td>1</td><td>2</td><td>3</td></tr></table></body></html>"));
    fout.Close();
}
catch
{
    Toast.MakeText(context, context.GetString("Please check your storage configuration.").Show();
}

if (Build.VERSION.SdkInt < BuildVersionCodes.N)
{
    share.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(file.AbsoluteFile));
}
else
{
    share.AddFlags(ActivityFlags.GrantReadUriPermission);
    share.PutExtra(Intent.ExtraStream, Android.Net.Uri.Parse(file.Path));
}
share.PutExtra(Intent.ExtraSubject, $"Meeting {DateTime.Now.ToString("dd-MM-yyyy")}");
context.StartActivity(Intent.CreateChooser(share, "Email:"));

CreateDirFile function:

private Java.IO.File CreateDirFile(string fileName)
{
    string root = null;
    if (Android.OS.Environment.IsExternalStorageEmulated)
    {
        root = Android.OS.Environment.ExternalStorageDirectory.ToString();
    }
    else
    {
        root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
    }

    Java.IO.File myDir = new Java.IO.File($"{root}/Meetings");
    myDir.Mkdir();

    Java.IO.File file = new Java.IO.File(myDir, fileName);

    if (file.Exists())
    {
        file.Delete();
        file.CreateNewFile();
    }

    return file;
}

I have tested many combinations and even applied the following code Android.Net.Uri.Parse(file.Path) as it's suggested in different answers from SO or other forums, but it doesn't work as expected.

Have any of you experienced similar issue? Do you know what should I change? Thanks in advance.

Best Answer

  • FedericoNavarreteFedericoNavarrete SV ✭✭
    Accepted Answer

    This is the final solution:

    In the OnCreate event:

    if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
    {
        StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
                            .PenaltyDeathOnFileUriExposure()
                            .Build();
        StrictMode.SetVmPolicy(policy);
    }
    

    Also, you need to have only this for the intent:

    share.PutExtra(Intent.ExtraStream, Android.Net.Uri.FromFile(file.AbsoluteFile));
    

    You don't need to validate the OS version.

Answers

Sign In or Register to comment.