There may be several instances when we would want to listen for the occurrence of events as they occur on the running Android system.
To listen for broadcast system events, we make use of a BroadcastReceiver
instance:
BroadcastReceiver
:public class WorkReceiver : BroadcastReceiver { public override void OnReceive( Context context, Intent intent) { } }
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:
[BroadcastReceiver]
attribute:[BroadcastReceiver] [IntentFilter(new []{ "xamarincookbook.Work" })]
RegisterReceiver()
method when we need to start listening:receiver = new WorkReceiver(); var filter = new IntentFilter("xamarincookbook.Work"); RegisterReceiver(receiver, filter);
UnregisterReceiver(receiver);
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:
LocalBroadcastManager
instance is available in the Xamarin Support Library v4 NuGet or component, so we have to install that first.receiver = new WorkReceiver(); var filter = new IntentFilter("xamarincookbook.Work"); var manager = LocalBroadcastManager.GetInstance(this); manager.RegisterReceiver(receiver, filter);
var manager = LocalBroadcastManager.GetInstance(this); manager.UnregisterReceiver(receiver);
var intent = new Intent("xamarincookbook.Work"); var manager = LocalBroadcastManager.GetInstance(this); manager.SendBroadcast(intent);
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.
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.
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.
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.
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.