BroadcastReceiver
BroadcastReceiver
are used to register for System and application events. Android run time system
will notify these components once the event for which they are register
happens.Upon notification the broadcast receiver will take appropriate action.
A broadcast receiver is a
component that responds to system-wide broadcast announcements. Many broadcasts
originate from the system—for example, a broadcast announcing that the screen
has turned off, the battery is low, or a picture was captured. Applications can
also initiate broadcasts—for example, to let other applications know that some
data has been downloaded to the device and is available for them to use.
Although broadcast receivers don't display a user interface, they may create a
status bar notification to alert the user when a broadcast event occurs. More
commonly, though, a broadcast receiver is just a "gateway" to other
components and is intended to do a very minimal amount of work. For instance,
it might initiate a service to perform some work based on the event. Other
examples of Broadcast Receiver from applications are new friend notifications,
new friend feeds, new message etc. on your facebook application.
Notifications like incoming
messages, wi-fi, and Bluetooth activation signal, new wi-fi in the range, low
battery signal are the real time examples of the BroadcastReceiver. Thus
BroadcastReceiver are everywhere in the android system.
Example of the system
broadcast Intent are:
Block Diagram of the system:
Registering BroadcastReceiver:
There are two ways to
register broadcast receiver:
- Static: Use <receiver> tag in your Manifest files (AndroidManifest.xml).
- Dynamic: Use Context.registerReceiver () method to register the receiver dynamically.
Implementation:
Create your own class extending BroadcastReceiver android class. If the registered broadcast event happens then android system will notify the Receiver class. Android system calls onReceive () method of the BroadcastReceiver.
Create your own class extending BroadcastReceiver android class. If the registered broadcast event happens then android system will notify the Receiver class. Android system calls onReceive () method of the BroadcastReceiver.
There are two major classes of broadcasts
that can be received:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager API. For the latter, you can use Context.startService() to send a command to the service.
From API level 11(Android 3.0) goAsynch() method is there to help. This method returns object of type PendingResult. Receiver will be alive till we call PendingResult.finish() .
- Normal broadcasts:(sent with
Context.sendBroadcast
) are completely asynchronous. All receivers of the broadcast are run in an undefined order, often at the same time. This is more efficient, but means that receivers cannot use the result or abort APIs included here.
- Ordered Broadcast:(Send with context.sendOrderedBroadcast()) These broadcast are delivered to one receiver at a time,As each receiver executes in turn,It can propagate result to the next receiver or it can completely abort the broadcast so that it wont be passed to other receivers.The order receivers run in can be controlled with the android:priority attribute of the matching intent filter;receivers with the same priority will be run in an arbitrary order.
Even in the case of normal broadcast,the system may in some situations revert to delivering the broadcast one receiver at a time.
Security:
Receivers used with Context APIs are by their nature a cross-application facility,so you must consider how other applications may be able to abuse your use of them.Some things to consider are
- The Intent namespace is global. Make sure that Intent action names and other strings are written in a namespace you own, or else you may inadvertently conflict with other applications.
- When you use registerReceiver(BroadcastReceiver, IntentFilter), any application may send broadcasts to that registered receiver. You can control who can send broadcasts to it through permissions described below.
- When you publish a receiver in your application's manifest and specify intent-filters for it, any other application can send broadcasts to it regardless of the filters you specify. To prevent others from sending to it, make it unavailable to them with android:exported="false".
- When you use sendBroadcast(Intent) or related methods, normally any other application can receive these broadcasts. You can control who can receive such broadcasts through permissions described below. Alternatively, starting with ICE_CREAM_SANDWICH, you can also safely restrict the broadcast to a single application with Intent.setPackage( ).
None of these issues exist when using LocalBroadcastManager, since intents broadcast it never go outside of the current process.
Access permissions can be enforced by either the sender or receiver of a broadcast.
To enforce a permission when sending, you supply a non-null permission argument to sendBroadcast(Intent, String) or sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle). Only receivers who have been granted this permission (by requesting it with the <uses-permission> tag in their AndroidManifest.xml) will be able to receive the broadcast.
To enforce a permission when receiving, you supply a non-null permission when registering your receiver -- either when callingregisterReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler) or in the static <receiver> tag in your AndroidManifest.xml. Only broadcasters who have been granted this permission (by requesting it with the <uses-permission> tag in their AndroidManifest.xml) will be able to send an Intent to the receiver.
From API level 11(3.0) android receiver will not receive any broadcast intent till application has run at least once .Application must not be stopped explicitly from android settings.
Access permissions can be enforced by either the sender or receiver of a broadcast.
To enforce a permission when sending, you supply a non-null permission argument to sendBroadcast(Intent, String) or sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle). Only receivers who have been granted this permission (by requesting it with the <uses-permission> tag in their AndroidManifest.xml) will be able to receive the broadcast.
To enforce a permission when receiving, you supply a non-null permission when registering your receiver -- either when callingregisterReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler) or in the static <receiver> tag in your AndroidManifest.xml. Only broadcasters who have been granted this permission (by requesting it with the <uses-permission> tag in their AndroidManifest.xml) will be able to send an Intent to the receiver.
From API level 11(3.0) android receiver will not receive any broadcast intent till application has run at least once .Application must not be stopped explicitly from android settings.
Receiver Lifecycle :
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager API. For the latter, you can use Context.startService() to send a command to the service.
From API level 11(Android 3.0) goAsynch() method is there to help. This method returns object of type PendingResult. Receiver will be alive till we call PendingResult.finish() .
Example 1:
Bellow is the simple example with event Intent.ACTION_BATTERY_LOW and displays dialog with message to the user.
AndroidManifest.xml will look like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.swapnil.batterytest"
android:versionCode="1"
android:versionName="1.0"
>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18"
/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.swapnil.batterytest.StartActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<receiver android:name="com.swapnil.batterytest.MyBatteryLevelReceiver"
>
<intent-filter>
<action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
</intent-filter>
</receiver>
</application>
</manifest>
BroadcastReceiver will look like this:
public class
MyBatteryLevelReceiver extends
BroadcastReceiver
{
@Override
public void
onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW))
{
Toast.makeText(context,R.string.battery_low_message,Toast.LENGTH_LONG).show();
// do your task
here.
}
}
}
If you want to check the battery level :
IntentFilter ifilter = new
IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus =
context.registerReceiver(null, ifilter);
int level =
batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale =
batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
int percent =
(level*100)/scale;
if(percent <=
10 && percent > 5)
{
}
Registering for custom events:
Android manifest will look like this
<?xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.swapmeen.custombroadcastreceiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18"
/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.swapmeen.custombroadcastreceiver.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<receiver android:name="com.swapmeen.custombroadcastreceiver.CustomBroadcastReceiver" >
<intent-filter>
<action android:name="com.swapmeen.custombroadcastreceiver.custombroadcast"
/>
</intent-filter>
</receiver>
</application>
</manifest>
You need to register receiver with custom BroadcastReceiver with
custom event which has unique action.
Following code is used to send the Intent to registered
BroadcastReceiver:
Intent intent = new Intent();
intent.setAction("com.swapmeen.custombroadcastreceiver.custombroadcast");
sendBroadcast(intent);
Above code can’t be used with system events. Above method is
asynchronous and returns immediately without waiting for
onReceive () to finish ().
Registering BroadcastReceiver Dynamically:
Following are the methods to register BroadcastReceiver:
Registering BroadcastReceiver Dynamically:
Following are the methods to register BroadcastReceiver:
Publicabstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter)
Public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handlerscheduler)
You must unregister receiver before exiting the activity otherwise
you will get leaked broadcast receiver error.
LocalBroadcastManager:
Helper to register for and send broadcasts of Intents to local objects
within your process. This is has a number of advantages over
sending global broadcasts with sendBroadcast(Intent):
- You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
- It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
- It is more efficient than sending a global broadcast through the system.
- This is faster and secure method.
public class StartActivity extends Activity {
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
}
@Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(custom_receiver,new IntentFilter("custom_data"));
}
private
BroadcastReceiver custom_receiver = new BroadcastReceiver()
{
@Override
public void
onReceive(Context context, Intent intent)
{
// Extract data included in the Intent
String message = intent.getStringExtra("data");
Log.d("TAG", "message
received: " + message);
}
};
@Override
protected void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(custom_receiver);
super.onPause();
}
@Override
public boolean
onCreateOptionsMenu(Menu menu) {
// Inflate the
menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.start, menu);
return true;
}
int i=0;
public void
sendbroadcast(View view)
{
Intent intent = new Intent("custom_data");
i++;
intent.putExtra("data", "Button
clicked i: "+i);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Using PackageManager with statically registered Receiver:
You can use the PackageManager to enable/disable a BroadcastReceiver in declared in the Manifest. The Broadcast Receiver will get fired only when it is enabled.
Use this to create a Component.
ComponentName component = new ComponentName(context, MyReceiver.class);
Check if the Component is enabled or disabled
int status = context.getPackageManager().getComponentEnabledSetting(component);
if(status == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
Log.d("receiver is enabled");
} else if(status == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
Log.d("receiver is disabled");
}
Enable/Disable the component(Broadcast Receiver in your case):
//Disable
context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED , PackageManager.DONT_KILL_APP);
//Enable
context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED , PackageManager.DONT_KILL_APP);
Sticky Broadcast Intent:
These are broadcasts whose data is held by the system after being finished, so that clients can quickly retrieve that data without having to wait for the next broadcast.
Permission required:
<uses-permission android:name="android.permission.BROADCAST_STICKY"/> - Allows an application to broadcast sticky intents.
Example:
Intent intent = new Intent("some.custom.action");
intent.putExtra("some_boolean", true);
sendStickyBroadcast(intent);
Perform a sendBroadcast(Intent) that is "sticky," meaning the Intent you are sending stays around after the broadcast is complete, so that others can quickly retrieve that data through the return value of registerReceiver(BroadcastReceiver, IntentFilter). In all other ways, this behaves the same as sendBroadcast(Intent).
// Register for the battery changed event
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
/ Intent is sticky so using null as receiver works fine
// return value contains the status
Intent batteryStatus = this.registerReceiver(null, filter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL;
boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY
Informative post indeed, I’ve being in and out reading posts regularly and I see a lot of engaging people sharing things and majority of the shared information is very valuable and so, here’s my fine read.
ReplyDeleteAndroid Training Institute in Chennai | Android Training Institute in anna nagar | Android Training Institute in omr | Android Training Institute in porur | Android Training Institute in tambaram | Android Training Institute in velachery