Home > Back-end >  How to use a BroadcastReceiver from .NET MAUI on Android?
How to use a BroadcastReceiver from .NET MAUI on Android?

Time:04-08

I have existing code from a sample app written for Xamarin.Android (not Forms). I need to use this in my new app written for .NET MAUI, the successor of all Xamarin. It uses a BroadcastReceiver to know when a USB device was detached from the phone. But this doesn't work in MAUI.

Here's the old code:

public partial class MainPage : ContentPage
{
    private BroadcastReceiver detachedReceiver;

    public MainPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        OnScanClicked(this, EventArgs.Empty);

        // TODO: Fix for MAUI
        //register the broadcast receivers
        detachedReceiver = new UsbDeviceDetachedReceiver(this);
        RegisterReceiver(detachedReceiver, new IntentFilter(UsbManager.ActionUsbDeviceDetached));
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        CloseDevice();

        // TODO: Fix for MAUI
        var temp = detachedReceiver; // copy reference for thread safety
        if (temp != null)
            UnregisterReceiver(temp);
    }

    private async void OnScanClicked(object sender, EventArgs args)
    {
        // Here's some code
    }

    class UsbDeviceDetachedReceiver : BroadcastReceiver
    {
        readonly MainPage mainPage;

        public UsbDeviceDetachedReceiver(MainPage mainPage)
        {
            this.mainPage = mainPage;
        }

        public override void OnReceive(Context context, Intent intent)
        {
            mainPage.OnScanClicked(null, null);
        }
    }
}

The code below the two TODO comments doesn't compile. I cannot figure out how this should be written for MAUI. Any ideas?

CodePudding user response:

In MAUI, code that in Xamarin.Android you would have put in Activity lifecycle events, can be done inside #if ANDROID, as part of the App Builder. This is documented in Platform Lifecycle Events.

Example from doc:

using Microsoft.Maui.LifecycleEvents;

namespace PlatformLifecycleDemo
{
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureLifecycleEvents(events =>
                {
#if ANDROID
                    events.AddAndroid(android => android
                        .OnActivityResult((activity, requestCode, resultCode, data) => LogEvent("OnActivityResult", requestCode.ToString()))
                        .OnStart((activity) => LogEvent("OnStart"))
                        .OnCreate((activity, bundle) => LogEvent("OnCreate"))
                        .OnBackPressed((activity) => LogEvent("OnBackPressed"))
                        .OnStop((activity) => LogEvent("OnStop")));
#endif
                    static void LogEvent(string eventName, string type = null)
                    {
                        System.Diagnostics.Debug.WriteLine($"Lifecycle event: {eventName}{(type == null ? string.Empty : $" ({type})")}");
                    }
                });

            return builder.Build();
        }
    }
}

In Xamarin.Android docs, we find Broadcast Receivers in Xamarin.Android.

Its example of using a custom Broadcast Receiver:

// --- This is Xamarin.Android code, not MAUI code. ---
[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity: Activity
{
    MySampleBroadcastReceiver receiver;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        receiver = new MySampleBroadcastReceiver();

        // Code omitted for clarity
    }

    protected override void OnResume()
    {
        base.OnResume();
        RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
        // Code omitted for clarity
    }

    protected override void OnPause()
    {
        UnregisterReceiver(receiver);
        // Code omitted for clarity
        base.OnPause();
    }
}

To keep MAUI's App Builder code concise, I would define methods that are called from the builder code:

public static class MauiProgram
...
#if ANDROID
private static void MyOnCreate(Activity activity, Bundle bundle)
{
    receiver = new MySampleBroadcastReceiver();
}
private static void MyOnResume(Activity activity)
{
    activity.RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
}
private static void MyOnPause(Activity activity)
{
    activity.UnregisterReceiver(receiver);
}
#endif

So that the builder code is always:

    ...
    builder
        .UseMauiApp<App>()
        .ConfigureLifecycleEvents(events =>
        {
#if ANDROID
            events.AddAndroid(android => android
                .OnCreate((activity, bundle) => MyOnCreate(activity, bundle))
                .OnResume((activity) => MyOnResume(activity))
                .OnPause((activity) => MyOnPause(activity)));
#endif
        });

In your case, place your old OnAppearing code into MyOnResume.



NOTE: It is possible to use .net 6 to write an Android app, without any mention of MAUI. That would be almost identical to writing a Xamarin.Android app, except for namespace changes.

To create a ".Net 6 Android" app, in VS 2022 (Preview), when "Create a new project", choose "Android Application (Preview)".

  • Related