Search code examples
xamarin.androidandroid-permissionsandroid-11

Attaching a file to email through Xamarin android app with Android API 30 (Android 11)


I have a Xamarin android app which attaches a log file to Email. With Android 10, this was working fine. But when I try this on Android 11 phones, it says " Unable to attach a file" in the email application. Then, I came across this blog explaining the package visibility in Android 11, and the changes that needs to be done https://devblogs.microsoft.com/xamarin/android-11-package-visibility/

SO, I made changes accordingly by adding this in my manifest file

<queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:scheme="mailto" />
    </intent>
</queries>

I do have permission for reading and writing external storage files.

Below is the code, which I use for attaching logs and sending it through email.

        Intent intent = new Intent(Intent.ActionSend);

        if ((ContextCompat.CheckSelfPermission(ysiCurrentActivity.Current.Activity, Android.Manifest.Permission.ReadExternalStorage) == Android.Content.PM.Permission.Granted) &&
            (ContextCompat.CheckSelfPermission(ysiCurrentActivity.Current.Activity, Android.Manifest.Permission.WriteExternalStorage) == Android.Content.PM.Permission.Granted))
        {
            ysiMainActivity activity = (ysiMainActivity)ysiCurrentActivity.Current.Activity;

            if (activity.GetExternalFilesDir(null) != null && !string.IsNullOrWhiteSpace(activity.GetExternalFilesDir(null).AbsolutePath))
            {
                string sFilePath = Path.Combine(activity.GetExternalFilesDir(null).AbsolutePath, "MobileAppLogs.log");
                if (!File.Exists(sFilePath))
                {
                    FileStream fileStream = new FileStream(sFilePath, FileMode.Create);
                    fileStream.Dispose();
                }
                using (StreamWriter streamWriter = new StreamWriter(sFilePath, false))
                {
                    streamWriter.Write(logs);
                }

                Java.IO.File file = new Java.IO.File(sFilePath);
                file.SetReadable(true, false);
                Android.Net.Uri uri = Android.Net.Uri.FromFile(file);

                intent.SetData(Uri.Parse("mailto:"));
                intent.SetType("message/rfc822");
                intent.PutExtra(Intent.ExtraSubject, "Logs");
                intent.PutExtra(Intent.ExtraStream, uri);

                ysiCurrentActivity.Current.Activity.StartActivity(Intent.CreateChooser(intent, "Send email"));
            }
        }
        else
        {
            return false;
        }

Even after adding the manifest changes, I still cannot attach the logs to email. Am i still missing something.

enter image description here


Solution

  • You can use Xamarin.Essentials: Email to achieve this.

    The Email class enables an application to open the default email application with a specified information including subject, body, and recipients.

    When we check part File Attachments,we could find that:

    This feature enables an app to email files in email clients on the device. Xamarin.Essentials will automatically detect the file type (MIME) and request the file to be added as an attachment. Every email client is different and may only support specific file extensions, or none at all.

    Here is a sample of writing text to disk and adding it as an email attachment:

    var message = new EmailMessage
    {
        Subject = "Hello",
        Body = "World",
    };
    
    var fn = "Attachment.txt";
    var file = Path.Combine(FileSystem.CacheDirectory, fn);
    File.WriteAllText(file, "Hello World");
    
    message.Attachments.Add(new EmailAttachment(file));
    
    await Email.ComposeAsync(message);
    

    Note:

    If your project's Target Android version is set to Android 11 (R API 30) you must update your Android Manifest with queries that are used with the new package visibility requirements.

    Open the AndroidManifest.xml file under the Properties folder and add the following inside of the manifest node:

    <queries>
      <intent>
        <action android:name="android.intent.action.SENDTO" />
        <data android:scheme="mailto" />
      </intent>
    </queries>
    

    For more details,check:https://learn.microsoft.com/en-us/xamarin/essentials/email?context=xamarin%2Fandroid&tabs=android&WT.mc_id=docs-xamarinblog-jamont.