Hello Guys!!! Wishing you all Doing Well !!!!
Definition
Definition
A BroadcastReceiver is
an Android app component that responds to system-wide broadcast
announcements.
Explanation
Device screen
on or off, Battery is getting Low or Battery start charging,
Camera captured some image all this event get broadcast by Android
System. Apart from these system broadcast, App can also broadcast there
event like SMS app broadcasting that an SMS has being received and let
other apps know about this event so that they can trigger some action.
Unlike Activities
broadcast receivers do not have any user interface but may create a status bar
notification. It is intended to do minimal amount of work and can delegate
hardcore jobs to Services.
So you can say
broadcast receivers are like hidden app components that can register for various
system or application events (intents). Once any of those events occur the
system notifies all the registered broadcast receivers and brings them up into
action which could be notifying the user or perform some other job.
A receiver can be
registered via the AndroidManifest.xml file.
Alternatively to this
static registration, you can also register a receiver dynamically via the Context.registerReceiver() method.
The implementing class
for a receiver extends the BroadcastReceiver class.
If the event for which
the broadcast receiver has registered happens, theonReceive() method of the receiver is called by the
Android system.
Type of Broadcast
- Global Broadcast
- Local Broadcast
Local Broadcast :- If you don't need to send
broadcasts across applications, consider using this class with LocalBroadcastManager. This will give us a much more efficient
implementation (no cross-process communication needed) and allow us to avoid
thinking about any security issues related to other applications being able to
receive or send your broadcasts. simple example of how to use it.
// Generally in your onResume()
LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context,
Intent intent) {
String message = intent.getStringExtra("foo");
Log.d("LocalBroadcastManager", "foo : " + message);
}
}, new IntentFilter("my-custom-event"));
We
saw how to register, now here’s how to send an intent to it:
// Send
Intent intent = new Intent("my-custom-event");
intent.putExtra("foo", "bar");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Global Broadcast
:- Global
Broadcast sent across the application( when cross-process communication
needed). Any application can receive(based on permission any if you
provided, only intended app receive it)it.
Type of Global
Broadcast :-
- Normal Broadcasts
- Ordered Broadcasts
Normal Broadcast :- It is sent with Context.sendBroadcast(). It is completely asynchronous, i.e.,
the broadcasts events/intents are received by all the receivers in an
asynchronous fashion. The receivers are run in an undefined order, often at the
same time. It’s efficient but receivers cannot use results from other
receivers or abort the entire chain of execution at a certain level.
Ordered Broadcast :- It is sent with Context.sendOrderedBroadcast(). It is delivered to one receiver at
a time. The order can be controlled withandroid:priority attribute of the matching intent-filter. Receivers with
same priority will be executed in a random order. As each receiver
executes in order, it can transmit the result to the next one or even abort the
entire broadcast chain so that no other receivers receive the
broadcast intent and are executed.
Creating a
BroadcastReceiver
Let’s quickly see how
to implement a broadcast receiver
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
@Override
public void onReceive(Context context,
Intent intent) {
// This method is called when this
BroadcastReceiver receives an Intent broadcast.
Toast.makeText(context, "Action: " + intent.getAction(), Toast.LENGTH_SHORT).show();
}
}
Registering the
Broadcast Receiver
We’re done with the
creation but it needs to be registered so that it can receive events (intents).
There are two ways to do this:
- Statically in the manifest file.
- Dynamically in the code.
Registering
BroadcastReceiver in the Manifest File
<receiver android:name="com.example.androidtest.MyReceiver"android:enabled="true" android:exported="true" >
<intent-filter>
<action android:name="com.example.androidtest.BroadcastReceiver" />
</intent-filter>
</receiver>
We use the
<receiver> tag to register our broadcast receiver with an intent
filter.Basically using intent filters we tell the system any intent that
matches our criterias (subelements) should get delivered to that specific app
component (a broadcast receiver in this case).
Registering
BroadcastReceiver Programatically(Dynamically in the
code)
IntentFilter filter = new IntentFilter("com.example.androidtest.BroadcastReceiver");
MyReceiver myReceiver = new MyReceiver();
registerReceiver(myReceiver, filter);
First we created an
IntentFilter object that specifies which event/intent our receiver will listen
to. In this case it’s com.example.androidtest.BroadcastReceiver which is a
custom action name, could be anything but generally the java package naming
convention is followed. We’ll use this action name again while sending a
broadcast that will be handled by this receiver.
Then we instantiate our
broadcast receiver and call Context.registerReceiver() to actually register our
receiver that will be called and run in the main application thread.
It’s important to note
that when we register a receiver in this way, it lives for as long as the
component that does the registration lives. Once the component that had made
the registerReceiver() call is destroyed sendBroadcast() will also stop
working, hence the receiver won’t receive anymore be it an event generated from
an app or the system. Whereas with the previous method where we registered via
the manifest file, this is not the case. When registering a receiver in Activity.onResume(),
it is strongly suggested to unregister them receivers in Activity.onPause() to
avoid unnecessary system overhead as intents won’t be received when paused
anyway.
@Overrideprotected void onPause() {
unregisterReceiver(mReceiver);
super.onPause();
}
Creating and Sending the
Broadcast Event/Intent
We’ve seen how to create
a broadcast receiver and then register it statically or dynamically. Finally we
need to learn how to create a broadcast intent and send it to our receiver.
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setAction("com.example.androidtest.BroadcastReceiver");
intent.putExtra("Foo", "Bar");
sendBroadcast(intent);
Second line where I
setFLAG_INCLUDE_STOPPED_PACKAGES –
that’s interesting. This flag basically means include intent
filters of stopped
applications too in the list of potential targets to resolve
against. Similarly
there isFLAG_EXCLUDE_STOPPED_PACKAGES that
does the opposite, i.e., excluding. When neither or both of
them are specified
then the default behaviour is including but in case of
broadcast receivers
the system addsFLAG_EXCLUDE_STOPPED_PACKAGES to
all broadcast intents by default. More on this subject here.
STOPPED STATE of an app is when it is
installed but not
launched or force stopped from the application manager tool.
Pending Intents
PendingIntent is sort of
an intent whose execution can be delayed and not executed right away using
something like startActivity() or startActivityForResult(), but in the future.
It’s an object which acts as a wrapper around an Intent object and passed on to
another app. This way we can grant permission to the foreign application to
execute the underlying Intent as if it were executed from our very own app’s
process.
When an Intent is given
to a foreign app that ships with Android or is a third party app, then they
execute it with their own permissions. Whereas a PendingIntent can wrap that
Intent which the foreign app executes with your own app’s permission.
Let’s see an example
where we’ll create a PendingIntent and pass it on to an AlarmManager using
which we’ll access the system’s alarm services that’ll allow us to schedule a
piece of code to be run at some point in the future (in our case after 3
seconds).
// In the MainActivity.onCreate()
int seconds = 3;
// Create an intent that will be wrapped in PendingIntent
Intent intent = new Intent(this, MyReceiver.class);
// Create the pending
intent and wrap our intent
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0);
// Get the alarm
manager service and schedule it to go off after 3s
AlarmManager alarmManager = (AlarmManager)
getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + (seconds * 1000), pendingIntent);
Toast.makeText(this, "Alarm set in " + seconds + " seconds", Toast.LENGTH_LONG).show();
Hi. Well explained. But I still have one doubt:
ReplyDeleteYou put the unregisterReceiver within a onPause function.
I need to detect the event of connectivity to Internet (Connection, Disconnection & Change). But where within the Main Code to unregisterReceiver after the connectivity status has been detected? If I do not unregisterReceiver, I get a leaked broadcast receiver error.
Hi,
ReplyDeleteThe Android documentation doesn't prescribe a single place to register/unregister broadcast receivers. but it mentions both onStart()/onStop() and onResume()/onPause() as possibilities.
The biggest factor in making this decision is, when does your receiver need to be able to do its job? This will determine when to register and unregister it.
Does the receiver need to do something about the broadcast only when the activity is in focus? If so, you can register/unregister it in onReceive()/onPause().
Does the receiver need to do something when visible, even if it doesn't have focus (e.g. when a dialog is being shown)? If so, use onStart()/onStop() to register/unregister
Does the receiver need to know about the broadcast even when the activity isn't visible?
For example, does it need to remember that something has happened, so that when the activity becomes visible, it can reflect the resulting state of affairs?
Then you need to use onCreate()/onDestroy() to register/unregister. (Note there are other ways to implement this kind of functionality.)
Note:- 1. If you register in onStart(), don't also register them in onResume(), because that would be redundant: onResume() is never called without onStart() being called first.
2. Also keep in mind that it's best to keep onPause() as light as possible:
Very useful information that you have shared and it is very useful to me.Thanks for sharing the information with us.
ReplyDeleteios app development company in chennai