We have
discussed about broadcasts by Android system in the previous post PART1 and we are
going to discuss about Broadcasts by the user in this post.
User also can send broadcasts whenever he
wants. For ex: On click of a button OR on successful download of a file. So the
receivers who are intended to receive this announcement can receive the message
and react. Registering, Implementing and unregistering the receiver for broadcasts
by the user are same as we discussed previously in PART1. The
only difference is user has to send the announcement of event explicitly.
sendBroadcast() method is used to send the broadcasts explicitly.
We should use same action name while registering the
receiver and sending the broadcast as below.
Registering statically:
<receiver android:name=".MyReciever" >
<intent-filter>
<action android:name="com.smartmobsolutions.custom_broadcast_action"/>
</intent-filter>
</receiver>
Or you can register dynamically as below:
IntentFilter iff = new IntentFilter("com.smartmobsolutions.custom_broadcast_action");
registerReceiver(yourReceiverClassObject,
iff);
On click of a button, you can send broadcasts in 2 simple
steps:
1.
Create an intent
by passing the action name to the constructor of Intent class. Or you can also
create an empty intent and set the action by using setAction() of Intent class.
Optionally you can send some data to the
receivers using putExtra() methods. You can get back this intent (which is
being used to broadcast) as one of parameters of onReceive() method of your
receiver class.
2.
Pass intent to
sendBroadcast() method.
Intent intent = new Intent();
intent.setAction("com.smartmobsolutions.custom_broadcast_action");
intent.putExtra(“key”, your_data);
sendBroadcast(intent);
So, now we’ve
sent a broadcast explicitly. All the receivers (means applications) who are
registered for the same event will get triggered now.
public class MyReciever extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String
data = intent.getStringExtra("key");
//The task to do when
the required event happens.
}
}
In this way also
you can share the data across the applications. You can set the priority if you want the
receiver to get triggered first among all others as discussed in PART1.
NOTE 1: As of Android 3.1 the Android system
excludes all receivers from receiving intents by default if the corresponding
application has never been started by the user or if the user explicitly
stopped the application via the Android menu (in Manage → Application).
This is an additional security feature as the user can be sure that only the
applications he started will receive broadcast intents. This does not mean the user has to start the
application again after a reboot. The Android system remembers that the user
already started it. Only one start is required without a forced stop by the
user.
NOTE 2: All the receivers are triggered in
asynchronous manner. In other words, sendBroadcast() will send the broadcast
and return immediately i.e. It doesn’t wait until all the receivers who are
registered for matching event have triggered and executed.
(NOTE1 Attribution: Vogella)
Ordered
Broadcasts: There might be a situation where you need to receive the result
from the receiver to the calling component (i.e. most probably an activity). A
normal broadcast will be received by receivers asynchronously and reacts. But
an OrderedBroadcast receives the event, reacts and returns the result to
calling component. sendOrderedBroadcast() method is used to send Ordered
Broadcasts. One of the arguments of
sendOrderedBroacast() is result receiver or final receiver which is used to get
the result in the calling component.
Main.xml
:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
tools:context=".MainActivity"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="sendOrederedEvent"
android:text="Send Ordered Broadcast"
android:textColor="@android:color/black"
android:textSize="17sp"
android:textStyle="bold" />
</RelativeLayout>
MainActivity.java:
public class MainActivity extends Activity {
private static final String EVENT_ACTION_NAME = "com.smartmobsolutions.android.ordered_broadcastreceivers_demo_app";
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void sendOrederedEvent(View v){
Intent i = new Intent(EVENT_ACTION_NAME);
sendOrderedBroadcast(i, null, finalResultReceiver, null, Activity.RESULT_OK, null, null);
}
private
BroadcastReceiver finalResultReceiver = new
BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent){
Toast.makeText(context, "Final Result
Receiver",Toast.LENGTH_SHORT).show();
Bundle
results = getResultExtras(true);
Toast.makeText(context, "Result =
"+results.getString("result2"), Toast.LENGTH_SHORT).show();
}
};
}
Register a receiver with priority.
Give max priority to get it triggered first.
<receiver android:name=".Receiver1">
<intent-filter android:priority="2">
<action android:name="com.smartmobsolutions.android.ordered_broadcastreceivers_demo_app"/>
</intent-filter>
</receiver>
And create below Receiver1.java in
same app:
public class Receiver1 extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Receiver1
triggered", Toast.LENGTH_SHORT).show();
Bundle
results = getResultExtras(true);
results.putString("result1",
"result in receiver1");
}
}
Create
another application with the Receiver of same event. Below is the Receiver
class and registration of receiver class with low priority in manifest
public class Receiver2 extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,
"Receiver2 triggered", Toast.LENGTH_SHORT).show();
Bundle results = getResultExtras(true);
String resultInReceiver1 = results.getString("result1");
results.putString("result2",
resultInReceiver1+", result in receiver2");
}
}
<receiver android:name=".Receiver2">
<intent-filter android:priority="1">
<action android:name="com.smartmobsolutions.android.ordered_broadcastreceivers_demo_app"/>
</intent-filter>
</receiver>
So,
now we have two different applications with different receivers i.e Receiver1
with high priority in App1 and Receiver2 with low priority in App2. Both are
intended to receive same action event. So When you click the button in App1,
sendOrderedBroadcast() method will send an ordered broadcast to the receivers.
Receiver1 will get triggered first and pass the result to its next receiver(s).
Now the next receiver with max priority (i.e Receiver2) will get triggered and
receive the result from previous receiver and pass the result to its next
receivers if any with low priority, otherwise final receiver which is passed as
an argument to sendOrderedBroadcast() method will get triggered.
We
can even stop the broadcasting of events using abortBroadcast() method. i.e if
we use abortBroadcast() method in Receiver1 class (which has max priority) then
all other receivers who are registered for the same action (with lower
priority) will not get triggered so the result will be passed directly from
Receiver1 to final receiver in MainActivity.
This
is how we can broadcast the events/intents in an ordered manner and pass the
result back to calling component (i.e MainActivity in this example) .