How-to Integrate Helpful Support Emails in Mobile Apps with Insightful Data & Logs

In the mad rush to finish my most recent app, My Cadence, I forgot to integrate an essential feature. A feature that enables my users to easily get a hold of me to report issues or request features, which is of course email support. Both Google Play and the App Store enable you to supply a support website and email, however this is a very lack luster experience for both you and your users. For your users they need to go open the app store, find your app, and then find the support button. For you, you get no information about the user's device, operating system, or even your app information. With just a few lines of code and Xamarin.Essentials, you can create a great experience for you and your users.

Information Filled Email

You could just put a simple "email support" button that opens the default email app, but let's think about how we could pre-populate it with helpful data. The first thing to think about is what you need about your user's device and your app that may be helpful. This includes things like version number, build number, operating system version, manufacturer, and model. With AppInfo and DeviceInfo APIs you can easily populate a string and generate an email with a few lines of code:

var builder = new StringBuilder();
builder.AppendLine($"App Version: {AppInfo.VersionString} | Build: {AppInfo.BuildString}");
builder.AppendLine($"OS: {DeviceInfo.Platform}");
builder.AppendLine($"OS Version: {DeviceInfo.VersionString}");
builder.AppendLine($"Manufacturer: {DeviceInfo.Manufacturer}");
builder.AppendLine($"Device Model: {DeviceInfo.Model}");
builder.AppendLine(string.Empty);
builder.AppendLine("Please let me know what issues you are having here:");

var message = new EmailMessage
{
    Subject = "My Cadence Support",
    To = new List<string>(new []{ "example@email.com" }),
    Body = builder.ToString(),
};

await Email.ComposeAsync(message);

Logger

This information is great, but you may want to additional logs and debug information. I regularly use System.Diagnostics.Debug.WriteLine() when debugging my app to print information, so I thought to myself... what if I enabled uses to gather all this debug information and sent it to me. So, I first created a setting that I could enable users to turn on and off with the Preferences API:

public static bool DebugMode
{
   get => Preferences.Get(nameof(DebugMode), false);
   set => Preferences.Set(nameof(DebugMode), value);
}

Then, I created a simple Logger class that I could think of that would simply append a line onto a StringBuilder in memory.

public static class Logger
{
    static Logger()
    {
        Init();
    }
    public static void Init()
    {
        DebugMode = Settings.DebugMode;
    }
    public static StringBuilder Log = new StringBuilder();
    public static bool DebugMode { get; set; }

    public static void AppendLine(string line)
    {
        Debug.WriteLine(line);
        if (!DebugMode)
            return;

        Log.AppendLine(line);
    }
}

While I do acknowledge that this may not be the "best" solution and there are tons of logging libraries out there, this one was very easy for me to implement in about 30 seconds.

Attach Logs to Email

Now, once I have the logs all setup, I can use Xamarin.Essentials again to attach the logs by writing the StringBuilder directly to a file in the cache and the send it my way!

var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
var fn = $"log_{timestamp}.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, Logger.Log.ToString());

message.Attachments.Add(new EmailAttachment(file));

This method has already helped me fine and fix a few bugs in my app and really streamlines communication with my users.