Integrating with Xamarin Forms Application

Xamarin Forms error handling for the .NET SDK

Working Sample

For the working sample, please look here.

Recommended Rollbar Modules/Packages

Whenever you are trying to integrate Rollbar.NET SDK into an existing Xamarin-based application, the most optimal way is to do it via our Rollbar module. Optionally, you may want to also use other modules/packages of the SDK: Rollbar.App.Config or Rollbar.AppSettings.Json and Rollbar.OfflinePersistence:

dotnet add package Rollbar

// optionally:
dotnet add package Rollbar.App.Config
dotnet add package Rollbar.AppSettings.Json
dotnet add package Rollbar.OfflinePersistence

Modify your Xamarin Forms Shared Project

Add RollbarHelper.cs using the following boilerplate code for its content:

namespace Sample.Xamarin.Forms
{
  using System;
  using System.Threading.Tasks;

  using Rollbar;
  using Rollbar.DTOs;
  
  using Samples;

  /// <summary>
  /// Class RollbarHelper.
  /// A utility class aiding in Rollbar SDK usage.
  /// </summary>
  public static class RollbarHelper
  {
    public static readonly TimeSpan RollbarTimeout = TimeSpan.FromSeconds(10);

    /// <summary>
    /// Registers for global exception handling.
    /// </summary>
    public static void RegisterForGlobalExceptionHandling()
    {
      AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
      {
        var newExc = new System.Exception(
          "CurrentDomainOnUnhandledException", 
          args.ExceptionObject as System.Exception
        );
       
        // report the exception to Rollbar:
        RollbarLocator
          .RollbarInstance
          .AsBlockingLogger(RollbarTimeout)
          .Critical(newExc);
      };

      TaskScheduler.UnobservedTaskException += (sender, args) =>
      {
        var newExc = new ApplicationException(
          "TaskSchedulerOnUnobservedTaskException", 
          args.Exception
        );
        
	      // report the exception to Rollbar:
        RollbarLocator
          .RollbarInstance
          .AsBlockingLogger(RollbarTimeout)
          .Critical(newExc);
      };
    }

    /// <summary>
    /// Configures the Rollbar singleton-like infrastructure.
    /// </summary>
    public static void ConfigureRollbar()
    {
      // create valid Rolbar configuration:
      RollbarInfrastructureConfig rollbarInfrastructureConfig = 
        new RollbarInfrastructureConfig(
          RollbarSamplesSettings.AccessToken,
          RollbarSamplesSettings.Environment
        );

      // optionally:
      RollbarDataSecurityOptions dataSecurityOptions = 
        new RollbarDataSecurityOptions();
      dataSecurityOptions.ScrubFields = new string[]
      {
        "access_token", // normally, you do not want scrub this specific field (it is operationally critical), but it just proves safety net built into the notifier... 
        "username",
      };
      rollbarInfrastructureConfig
        .RollbarLoggerConfig
        .RollbarDataSecurityOptions
        .Reconfigure(dataSecurityOptions);

      // optionally:
      RollbarPayloadAdditionOptions payloadAdditionOptions = 
        new RollbarPayloadAdditionOptions();
      payloadAdditionOptions.Person = new Person("007")
      {
        Email = "[email protected]",
        UserName = "JBOND"
      };
      rollbarInfrastructureConfig
        .RollbarLoggerConfig
        .RollbarPayloadAdditionOptions
        .Reconfigure(payloadAdditionOptions);

      RollbarInfrastructure.Instance.Init(rollbarInfrastructureConfig);

      // optionally, to monitor Rollbar internal events:
      RollbarInfrastructure
        .Instance
        .QueueController
        .InternalEvent += OnRollbarInternalEvent;
    }

    /// <summary>
    /// Called when rollbar internal event is detected.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="RollbarEventArgs" /> instance containing the event data.</param>
    private static void OnRollbarInternalEvent(
      object sender, 
      RollbarEventArgs e
    )
    {
      Console.WriteLine(e.TraceAsString());

      RollbarApiErrorEventArgs apiErrorEvent = e as RollbarApiErrorEventArgs;
      if (apiErrorEvent != null)
      {
        //TODO: handle/report Rollbar API communication error event...
        return;
      }
      CommunicationEventArgs commEvent = e as CommunicationEventArgs;
      if (commEvent != null)
      {
        //TODO: handle/report Rollbar API communication event...
        return;
      }
      CommunicationErrorEventArgs commErrorEvent = e as CommunicationErrorEventArgs;
      if (commErrorEvent != null)
      {
        //TODO: handle/report basic communication error while attempting to reach Rollbar API service... 
        return;
      }
      InternalErrorEventArgs internalErrorEvent = e as InternalErrorEventArgs;
      if (internalErrorEvent != null)
      {
        //TODO: handle/report basic internal error while using the Rollbar Notifier... 
        return;
      }
    }

  }
}

Modify your Xamarin Forms UWP Project

Update your App.xaml.cs like so:

namespace Sample.Xamarin.Forms.UWP
{
  
  using System;

  using Windows.ApplicationModel;
  using Windows.ApplicationModel.Activation;
  using Windows.UI.Xaml;
  using Windows.UI.Xaml.Controls;
  using Windows.UI.Xaml.Navigation;

  using Rollbar;
  using xf = Xamarin.Forms;

  /// <summary>
  /// Provides application-specific behavior to supplement the default Application class.
  /// </summary>
  sealed partial class App : Application
  {
    /// <summary>
    /// Initializes the singleton application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
      // configure Rollbar:
      RollbarHelper.ConfigureRollbar();

      // basic senity check:
      RollbarLocator.RollbarInstance
        .Info("Xamarin.Forms sample: Hello world! Xamarin is here...");

      // subscribe to all known unhandled exception events application-wide:
      RollbarHelper.RegisterForGlobalExceptionHandling();
      this.UnhandledException += App_UnhandledException;

      this.InitializeComponent();
      this.Suspending += OnSuspending;
    }

    private void App_UnhandledException(
      object sender, 
      Windows.UI.Xaml.UnhandledExceptionEventArgs e
    )
    {
      // report the exception to Rollbar:
      RollbarLocator
        .RollbarInstance
        .AsBlockingLogger(RollbarHelper.RollbarTimeout)
        .Critical(e.Exception);
    }

  }
}

Modify your Xamarin Forms Android Project

Update your MainActivity.cs like so:

namespace Sample.Xamarin.Forms.Droid
{
  //...
  using Rollbar;
  //...

  [Activity(
    Label = "Sample.Xamarin.Forms", 
    Icon = "@drawable/icon", 
    Theme = "@style/MainTheme", 
    MainLauncher = true, 
    ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation
  )]
  public class MainActivity 
    : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
  {
      protected override void OnCreate(Bundle bundle)
      {
        // configure Rollbar:
        RollbarHelper.ConfigureRollbar();

        // basic senity check:
        RollbarLocator.RollbarInstance
          .Info("Xamarin.Forms sample: Hello world! Xamarin is here @MainActivity.OnCreate(...) ...");

        //subscribe to all known unhandled exception events application-wide
        RollbarHelper.RegisterForGlobalExceptionHandling();
        AndroidEnvironment.UnhandledExceptionRaiser += 
          AndroidEnvironment_UnhandledExceptionRaiser;

        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);

        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App());
      }

      private void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e)
      {
        var newExc = 
          new System.Exception("UnhandledExceptionRaiser", e.Exception);
        
	      // report the exception to Rollbar:
        RollbarLocator
          .RollbarInstance
          .AsBlockingLogger(RollbarHelper.RollbarTimeout)
          .Critical(newExc);
      }
  }
}

Modify your Xamarin Forms iOS Project

Update your AppDelegate.cs like so:

namespace Sample.Xamarin.Forms.iOS
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Threading.Tasks;
  
  using Foundation;
  using UIKit;

  using Rollbar;

  // The UIApplicationDelegate for the application. This class is responsible for launching the 
  // User Interface of the application, as well as listening (and optionally responding) to 
  // application events from iOS.
  [Register("AppDelegate")]
  public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
  {
    //
    // This method is invoked when the application has loaded and is ready to run. In this 
    // method you should instantiate the window, load the UI into it and then make the window
    // visible.
    //
    // You have 17 seconds to return from this method, or iOS will terminate your application.
    //
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
      // configure Rollbar:
      RollbarHelper.ConfigureRollbar();
      
      //subscribe to all known unhandled exception events application-wide:
      RollbarHelper.RegisterForGlobalExceptionHandling();

      global::Xamarin.Forms.Forms.Init();
      LoadApplication(new App());

      return base.FinishedLaunching(app, options);
    }

    /// <summary>
    /// Informs the app that the activity of the <paramref name="userActivityType" /> type could not be continued, and specifies a <paramref name="error" /> as the reason for the failure.
    /// </summary>
    /// <param name="application">To be added.</param>
    /// <param name="userActivityType">To be added.</param>
    /// <param name="error">To be added.</param>
    /// <remarks>To be added.</remarks>
    public override void DidFailToContinueUserActivitiy(
      UIApplication application, 
      string userActivityType, 
      NSError error
    )
    {
      // collect data about the NSError:
      IDictionary<string, object> custom = new Dictionary<string, object>();
      custom["NSError.Description"] = error.Description;
      custom["NSError.DebugDescription"] = error.DebugDescription;
      custom["NSError.Code"] = error.Code;
      custom["NSError.Domain"] = error.Domain;
      custom["NSError.LocalizedDescription"] = error.LocalizedDescription;
      custom["NSError.LocalizedFailureReason"] = error.LocalizedFailureReason;
      custom["NSError.LocalizedRecoveryOptions"] = error.LocalizedRecoveryOptions;
      custom["NSError.LocalizedRecoverySuggestion"] = error.LocalizedRecoverySuggestion;

      // capture the user activity type:
      string message = "NSError during user activity type: " + userActivityType;

      // report the error to Rollbar:
      RollbarLocator
        .RollbarInstance
        .AsBlockingLogger(RollbarHelper.RollbarTimeout)
        .Error(message, custom);

      base.DidFailToContinueUserActivitiy(application, userActivityType, error);
    }

  }
}