Xamarin.Tips – Calling Platform-Specific Code from a Portable Class Library – Xamarin.Forms DependencyService

For those who just want code: https://github.com/SuavePirate/Xamarin.HockeyApp.Portable

For those who just want the video: [VIDEO] Xamarin.Tips: Calling Platform-Specific Code from a PCL (Xamarin.Forms DependencyService)

As we develop our applications to be cross-platform, we try to share as much code between different platforms as possible. Many times, though, we have a need to call platform-specific code from that shared code; whether it be something such as playing a sound file, handling hardware readings, or using a third-party SDK that isn’t abstracted to be shareable.

In these examples, we will look at implementing parts of the HockeyApp SDK that are specific to the platform you are running against such as showing the Feedback control to ask your users to report bugs or give feedback.

There are a few ways to accomplish this, but in this post, we will look at using the Xamarin.Forms DependencyService.

The Xamarin.Forms DependencyService allows us to register implementations in our platform code as the implementation of an interface defined in our shared code. We can then use the Get() method from the DependencyService to get a reference to the platform code in our shared code.

To start, in our shared code, we will create an interface that will be implemented on our platforms:

public interface IHockeyService
{
    void Init();
    void GetFeedback();
}

 

Now in our platform projects, we will implement our IHockeyService. The important thing to note is the assembly level attribute tag we put over our namespace. This tag is what registers our implementation to the Dependency Service!

iOS:

[assembly: Xamarin.Forms.Dependency(typeof(HockeyService))]
namcespace YOUR_NAMESPACE
{
    public class HockeyService : IHockeyService
    {
        public HockeyService()
        {
        }

        public void GetFeedback()
        {
            BITHockeyManager.SharedHockeyManager.FeedbackManager.ShowFeedbackListView();
        }

        public void Init()
        {
            var manager = BITHockeyManager.SharedHockeyManager;
            manager.Configure("HOCKEY_APP_ID");
            manager.StartManager();
        }
    }
}

Android:

[assembly: Xamarin.Forms.Dependency(typeof(HockeyService))]</pre>
namcespace YOUR_NAMESPACE
{
    public class HockeyService : IHockeyService
    {
        private const string HOCKEYAPP_KEY = "HOCKEY_APP_ID";
        private readonly Android.App.Application _androidApp;
        private readonly Activity _context;

        public HockeyAppService(Activity context, Android.App.Application androidApp)
        {
            _context = context;
            _androidApp = androidApp;
        }

        public void GetFeedback()
        {
            FeedbackManager.ShowFeedbackActivity(_context.ApplicationContext);
        }

        public void Initialize()
        {
            CrashManager.Register(_context, HOCKEYAPP_KEY);
            MetricsManager.Register(_androidApp, HOCKEYAPP_KEY);
            UpdateManager.Register(_context, HOCKEYAPP_KEY);
            FeedbackManager.Register(_context, HOCKEYAPP_KEY);
        }
    }
}

Now we need to initialize the HockeyApp manager from our shared code.

App.xaml.cs

public App ()
{
    DependenyService.Get<IHockeyService>().Init();
}

Now that our service is registered to the DependencyService, we can make calls to it from our Shared code. In this example, we will add a button to a Xamarin.Forms page with a click handler that calls the service:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="YourNamespace.MainPage">

    <Button Text="Get feedback with the dependency service!"
            VerticalOptions="Center"
            HorizontalOptions="Center"
            Clicked="Feedback_Clicked"/>

</ContentPage>

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void Feedback_Clicked(object sender, EventArgs e)
    {
        DependencyService.Get<IHockeyService>().GetFeedback();
    }
}

Now our results will show that our shared code call to the service successfully shows the HockeyApp UI

simulator-screen-shot-feb-15-2017-1-47-26-pm

Xamarin.Tips – Calling Platform-Specific Code from a Portable Class Library – The Singleton Method

For those who just want code: https://github.com/SuavePirate/Xamarin.HockeyApp.Portable

For those who just want the video: [VIDEO] Xamarin.Tips: Calling Platform-Specific Code from a PCL (Singleton Method)

As we develop our applications to be cross-platform, we try to share as much code between different platforms as possible. Many times, though, we have a need to call platform-specific code from that shared code; whether it be something such as playing a sound file, handling hardware readings, or using a third-party SDK that isn’t abstracted to be shareable.

In these examples, we will look at implementing parts of the HockeyApp SDK that are specific to the platform you are running against such as showing the Feedback control to ask your users to report bugs or give feedback.

There are a few ways to accomplish this, but in this post, we will look at using the Singleton Method.

The Singleton Method is where we create a universal Singleton in our shared code that is initialized in our platform code, and then called from our shared code.

To start, in our shared code, we will create an interface that will be implemented on our platforms:

public interface IHockeyService
{
    void Init();
    void GetFeedback();
}

Then we create our actual Singleton in our shared code:

public class HockeyManager
{
    public static IHockeyService Current;
}

Now in our platform projects, we will implement our IHockeyService:

iOS:

public class HockeyService : IHockeyService
{
    public HockeyService()
    {
    }

    public void GetFeedback()
    {
        BITHockeyManager.SharedHockeyManager.FeedbackManager.ShowFeedbackListView();
    }

    public void Init()
    {
        var manager = BITHockeyManager.SharedHockeyManager;
        manager.Configure("HOCKEY_APP_ID");
        manager.StartManager();
    }
}

Android:

public class HockeyService : IHockeyService
{
    private const string HOCKEYAPP_KEY = "HOCKEY_APP_ID";
    private readonly Android.App.Application _androidApp;
    private readonly Activity _context;

    public HockeyAppService(Activity context, Android.App.Application androidApp)
    {
        _context = context;
        _androidApp = androidApp;
    }

    public void GetFeedback()
    {
        FeedbackManager.ShowFeedbackActivity(_context.ApplicationContext);
    }

    public void Initialize()
    {
        CrashManager.Register(_context, HOCKEYAPP_KEY);
        MetricsManager.Register(_androidApp, HOCKEYAPP_KEY);
        UpdateManager.Register(_context, HOCKEYAPP_KEY);
        FeedbackManager.Register(_context, HOCKEYAPP_KEY);
    }
}

Now we need to initialize our Singleton from our platform-specific code. In iOS, we will do this in our AppDelegate, and in Android – our MainActivity:

iOS

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    HockeyManager.Current = new HockeyService();
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    return base.FinishedLaunching(app, options);
}

Android:

protected override void OnCreate(Bundle bundle)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;
    base.OnCreate(bundle);
    HockeyManager.Current = new HockeyService(this, Application);
    global::Xamarin.Forms.Forms.Init(this, bundle);
    LoadApplication(new App());
}

Now we need to initialize the HockeyApp manager from our shared code.

App.xaml.cs

public App ()
{
    HockeyManager.Current.Init();
}

Now that our Singleton is created, we can make calls to it from our Shared code. In this example, we will add a button to a Xamarin.Forms page with a click handler that calls the service:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="YourNamespace.MainPage">

    <Button Text="Get feedback with a singleton!"
            VerticalOptions="Center"
            HorizontalOptions="Center"
            Clicked="Feedback_Clicked"/>

</ContentPage>
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void Feedback_Clicked(object sender, EventArgs e)
    {
        HockeyManager.Current.GetFeedback();
    }
}

Now our results will show that our shared code call to the Singleton successfully shows the HockeyApp UI

simulator-screen-shot-feb-15-2017-1-47-26-pm