Using BroadcastReceivers

There may be several instances when we would want to listen for the occurrence of events as they occur on the running Android system.

How to do it...

To listen for broadcast system events, we make use of a BroadcastReceiver instance:

  1. To listen for events, we need an instance of BroadcastReceiver:
    public class WorkReceiver : BroadcastReceiver {
      public override void OnReceive(
      Context context, Intent intent) {
      }
    }
  2. Often, broadcast receivers don't do much except starting a service, which does the work on a background thread:
    var service = new Intent(context, typeof(WorkService));
    context.StartService(service);

Once we have a broadcast receiver, we need to register it with the Android system. There are three ways to do this:

  • We can automatically register the receiver when the app is installed using the [BroadcastReceiver] attribute:
    [BroadcastReceiver]
    [IntentFilter(new []{ "xamarincookbook.Work" })]
  • We can also manually register the receiver using the RegisterReceiver() method when we need to start listening:
    receiver = new WorkReceiver();
    var filter = new IntentFilter("xamarincookbook.Work");
    RegisterReceiver(receiver, filter);
  • And then we can unregister it when we are finished:
    UnregisterReceiver(receiver);
  • Regardless if it was installed automatically or manually, we can broadcast an intent to these receivers using the SendBroadcast() method:
    var intent = new Intent("xamarincookbook.Work");
    SendBroadcast(intent);

If we are going to be listening for messages that are only broadcast from within our app, we can use the LocalBroadcastManager instance:

  1. The LocalBroadcastManager instance is available in the Xamarin Support Library v4 NuGet or component, so we have to install that first.
  2. Similar to manually registered receivers, we register the receiver with the local broadcast manager:
    receiver = new WorkReceiver();
    var filter = new IntentFilter("xamarincookbook.Work");
    var manager = LocalBroadcastManager.GetInstance(this);
    manager.RegisterReceiver(receiver, filter);
  3. We can unregister the receiver when we are finished:
    var manager = LocalBroadcastManager.GetInstance(this);
    manager.UnregisterReceiver(receiver);
  4. However, we have to broadcast a message through the local broadcast manager instead of the global broadcast manager:
    var intent = new Intent("xamarincookbook.Work");
    var manager = LocalBroadcastManager.GetInstance(this);
    manager.SendBroadcast(intent);

How it works...

A BroadcastReceiver instance is essentially an app component that listens for a specific global event to occur. Such events can be a change in Wi-Fi state, battery level, or the device booting up. Regardless of the event, broadcast receivers are very simple and only live as long as it takes to complete the execution of the OnReceive() method.

The OnReceive() method should be as short as possible and, and as a result, any long-running task should be assigned to a service instead of being executed directly. As soon as the method has completed, the receiver is marked as finished and ready to be disposed of. This is important when running asynchronous tasks. As the method will probably return before the background task has completed, the thread may be leaked or terminated unexpectedly.

Note

A BroadcastReceiver instance only lives as long as it takes for the OnReceive() method to return. Any running threads will be leaked.

We can register the receiver automatically when the user installs the app. This is especially useful for events that we want to listen for, even when the app is not running. To do this, we apply the [BroadcastReceiver] attribute to the receiver. Then, we apply the [IntentFilter] attribute to inform the Android system about the broadcast messages that we are waiting for.

However, this may not be necessary as we might only be listening for a message for a short period of time. This can be while downloading a file, or when we are interested in pausing the download when the user is no longer connected to Wi-Fi. In this case, we can dynamically register the receiver using the RegisterReceiver() method.

When we do this, we do not apply the attributes, but instead pass an instance of the receiver along with an instance of IntentFilter to the RegisterReceiver() method. We need to keep a reference to the receiver so that we can unregister it when we are finished.

Tip

A single instance of a broadcast receiver can be registered multiple times, each time with a different intent filter.

As soon as we no longer require the receiver to listen for messages, we unregister it by passing the instance of the receiver to the UnregisterReceiver() method. When we unregister a receiver, all registrations of that receiver are removed.

Note

A broadcast receiver that is registered in the OnResume() method of an activity should be unregistered in the OnPause() method.

If we are only listening for internal broadcasts, we can further cut down on system resources by registering with the LocalBroadcastManager. This implementation is more efficient, but we can only respond to internally broadcast messages.

In order to use the LocalBroadcastManager, we have to install the Android Support v4 library. This is found in either the Xamarin Support Library v4 NuGet or Component.

When we want to register a receiver with the local manager, we have to first obtain an instance of the manager using the static GetInstance() method. Once we have an instance, we can invoke the RegisterReceiver() and UnregisterReceiver() methods just as would invoke them on the Context type.

Tip

Unregistering receivers when they are not needed helps reduce the impact on system resources.

Finally, we can broadcast messages using the SendBroadcast() method. We simply pass an intent to this method, and each of the registered receivers will receive them. We can also add any data to the intent using the extras mechanism. When the receiver responds to the message, it can obtain the values from the intent.

If we have registered the receiver using the local broadcast manager, we have to broadcast the intents using the manager. Receivers registered with the local broadcast manager will not receive globally broadcast intents and globally registered receivers will not receive locally broadcast messages.

Tip

Using the LocalBroadcastManager to broadcast intents increases app security as data that is broadcast never leaves the app.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset