Android Programming
Unit-4 Broadcast receivers, notifications and services
Syllabus:
• Broadcast receiver
• Broadcasting events with intents
• Listening for broadcasts with broadcast receivers
• Broadcasting ordered intents
• Broadcasting sticky intents
• Pending intents
• Creating notifications
• Setting and customizing the notification tray UI
• Create, start and stop services
• Binding services to activities
• Using asynctasks to manage background processing
• Handler , Looper and Runnable
Broadcast receiver:
• Broadcast in android is the system-wide events that can occur when the device starts,
when a message is received on the device or when incoming calls are received, or
when a device goes to airplane mode, etc.
• Broadcast Receivers are used to respond to these systemwide events.
• Broadcast Receivers allow us to register for the system and application events, and
when that event happens, then the register receivers get notified
• There are mainly two types of Broadcast Receivers:
• Static Broadcast Receiver
Prof. Rahul Khandarkar 1
Android Programming
• Dynamic Broadcast Receivers
• Static Broadcast Receivers: These types of Receivers are declared in the manifest
file and works even if the app is closed.
• Dynamic Broadcast Receivers: These types of receivers work only if the app is
active or minimized
• Broadcast Receivers simply respond to broadcast messages from other applications or
from the system itself.
• These messages are sometime called events or intents.
• For example, applications can also initiate broadcasts to let other applications know
that some data has been downloaded to the device and is available for them to use, so
this is broadcast receiver who will intercept this communication and will initiate
appropriate action.
• There are following two important steps to make BroadcastReceiver works for the
system broadcasted intents − 1. Creating the Broadcast Receiver.
2. Registering Broadcast Receiver.
Creating the Broadcast Receiver:
• A broadcast receiver is implemented as a subclass of BroadcastReceiver class and
overriding the onReceive() method where each message is received as a Intent object
parameter.
public class MyReceiver extends BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent)
Prof. Rahul Khandarkar 2
Android Programming
Toast.makeText(context, "Intent Detected.",
Toast.LENGTH_LONG).show();
}
Registering Broadcast Receiver:
• An application listens for specific broadcast intents by registering a broadcast receiver
in AndroidManifest.xml file.
• Consider we are going to register MyReceiver for system generated event
ACTION_BOOT_COMPLETED which is fired by the system once the Android
system has completed the boot process.
Broadcast-Receiver:
<application
android:icon="@drawable/ic_launcher“
android:label="@string/app_name“
android:theme="@style/AppTheme" >
<receiver android:name=“MyReceiver”>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"> </action>
</intent-filter>
Prof. Rahul Khandarkar 3
Android Programming
</receiver>
</application>
• Now whenever your Android device gets booted, it will be intercepted by
BroadcastReceiver MyReceiver and implemented logic inside onReceive() will be
executed.
• There are several systems generated events defined as final static fields in the Intent
class.
android.intent.action.BATTERY_CHANGED
• Sticky broadcast containing the charging state, level, and other information about the
battery.
android.intent.action.BATTERY_LOW
• Indicates low battery condition on the device.
android.intent.action.BATTERY_OKAY
• Indicates the battery is now okay after being low.
android.intent.action.BOOT_COMPLETED
• This is broadcast once, after the system has finished booting.
android.intent.action.BUG_REPORT
• Show activity for reporting a bug.
android.intent.action.CALL
• Perform a call to someone specified by the data.
android.intent.action.CALL_BUTTON
• The user pressed the "call" button to go to the dialer or other appropriate UI for
placing a call.
android.intent.action.DATE_CHANGED
• The date has changed. android.intent.action.REBOOT
• Have the device reboot.
Prof. Rahul Khandarkar 4
Android Programming
Broadcasting Events with Intents:
• Broadcasting Intents is actually quite simple.
• Within your application component, construct the Intent you want to broadcast, and
use the sendBroadcast method to send it.
• Set the action, data, and category of your Intent in a way that lets Broadcast Receivers
accurately determine their interest.
• Consider the scenario, the Intent action string is used to identify the event being
broadcast, so it should be a unique string that identifies the event.
• By convention, action strings are constructed using the same form as Java packages,
as shown in the following snippet:
public static final String NEW_LIFEFORM_DETECTED =
“com.paad.action.NEW_LIFEFORM”;
• If you wish to include data within the Intent, you can specify a URI using the Intent’s
data property. You can also include extras to add additional primitive values.
Considered in terms of an event-driven paradigm, the extras Bundle equates to
optional parameters within an event handler.
• The skeleton code below shows the basic creation of a Broadcast Intent using the
action defined previously, with additional event information stored as extras. Intent
intent = new Intent(NEW_LIFEFORM_DETECTED);
intent.putExtra(“lifeformName”, lifeformType); intent.putExtra(“longitude”,
currentLongitude); intent.putExtra(“latitude”, currentLatitude);
sendBroadcast(intent);
Listening for broadcasts with broadcast receivers:
• Broadcast Receivers are used to listen for Broadcast Intents. To enable a Broadcast
Receiver, it needs to be registered, either in code or within the application manifest.
Prof. Rahul Khandarkar 5
Android Programming
When registering a Broadcast Receiver, you must use an Intent Filter to specify which
Intents it is listening for.
• To create a new Broadcast Receiver, extend the BroadcastReceiver class and override
the onReceive event handler as shown in the skeleton code below:
import
android.content.BroadcastReceiver;
import android.content.Context; import
android.content.Intent;
public class MyBroadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
//TODO: React to the Intent received.
}
}
• The onReceive method will be executed when a Broadcast Intent is received that
matches the Intent Filter used to register the receiver. The onReceive handler must
complete within 5 seconds, or the Application Unresponsive dialog will be displayed.
• Applications with registered Broadcast Receivers do not have to be running when the
Intent is broadcast for the receivers to execute. They will be started automatically
when a matching Intent is broadcast. This is excellent for resource management as it
lets you create event-driven applications that can be closed or killed, safe in the
knowledge that they will still respond to broadcast events.
• Typically, Broadcast Receivers will update content, launch Services, update Activity
UI, or notify the user using the Notification Manager. The 5-second execution limit
ensures that major processing cannot, as it should not, be done within the Broadcast
Receiver directly
Prof. Rahul Khandarkar 6
Android Programming
• The following example shows how to implement a Broadcast Receiver. In the
following sections, you will learn how to register it in code or in your application
manifest.
public class LifeformDetectedBroadcastReceiver extends BroadcastReceiver { public
static final String BURN = “com.paad.alien.action.BURN_IT_WITH_FIRE”;
@Override public void onReceive(Context context,
Intent intent) { // Get the lifeform details from the
intent.
Uri data = intent.getData();
String type = intent.getStringExtra(“type”); double
lat = intent.getDoubleExtra(“latitude”, 0); double
lng = intent.getDoubleExtra(“longitude”, 0);
Location loc = new Location(“gps”);
loc.setLatitude(lat); loc.setLongitude(lng);
if (type.equals(“alien”)) {
Intent startIntent = new Intent(BURN, data); startIn
tent.putExtra(“latitude”, lat);
startIntent.putExtra(“longitude”, lng);
context.startActivity(startIntent);
}
}
}
Broadcasting ordered intents:
Prof. Rahul Khandarkar 7
Android Programming
• When broadcasting an Intent using sendBroadcast, your Intent will be received by all
registered broadcast recievers, but you cannot control the order and they cannot
propagate results.
• In circumstances where the order in which the Broadcast Receivers receive the Intent
is important, or where you require the Receivers to be able to affect the Intent being
broadcast, you can use the sendOrderedBroadcast method.
sendOrderedBroadcast(intent, null);
Using this method, your Intent will be delivered to all registered Receivers in order of
priority
• We can optionally assign our own Broadcast Receiver, which will then receive the
Intent after it has been handled (and potentially modified) by all the other registered
Broadcast Receivers.
sendOrderedBroadcast(intent, null, myBroadcastReceiver, null,
Activity.RESULT_OK, null, null);
• When broadcasting an Intent using sendBroadcast, the Intent will be received by all
registered Broadcast Receivers, but we cannot control the order and they cannot
propagate results.
• In circumstances where the order in which the Broadcast Receivers receive the Intent
is important, or where we require the Receivers to be able to affect the Intent being
broadcast, we can use the sendOrderedBroadcast method.
sendOrderedBroadcast(intent, null);
• Using this method, the Intent will be delivered to all registered Receivers in order of
priority.
• We can optionally assign our own Broadcast Receiver, which will then receive the
Intent after it has been handled (and potentially modified) by all the other registered
Broadcast Receivers.
sendOrderedBroadcast(intent, null, myBroadcastReceiver, null,
Activity.RESULT_OK, null, null);
Broadcasting sticky intents:
• For efficiency reasons, some broadcasts are sticky.
Prof. Rahul Khandarkar 8
Android Programming
• When you call registerReceiver specifying an Intent Filter that matches a sticky
broadcast , the return value will be the sticky broadcast Intent.
• To broadcast a sticky Intent your application must have the BROADCAST_STICKY
uses-permission.
sendStickyBroadcast(intent);
• To remove a sticky intent call removeStickyBroadcast, passing in the sticky Intent to
remove.
removeStickyBroadcast(intent);
Pending intents:
• A PendingIntent is a reference to a token maintained by the system.
• Application A can pass a PendingIntent to application B in order to allow application
B to execute predefined actions on behalf of application A; regardless of whether
application A is still alive.
• A PendingIntent can be mutable, which means that the inner intent that specifies the
action can be updated by application B following the logic described in the fillIn()
documentation.
• In other words, the unfilled fields of a PendingIntent can be modified by a malicious
app and allow access to otherwise non-exported components of the vulnerable
application.
• Make sure action, component, and package are set to avoid the worst vulnerabilities
Intent intent = new Intent(intentAction);
// Or other component setting APIs e.g. setComponent, setClass
intent.setClassName(packageName, className);
PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), /*
requestCode= */ 0, intent, /* flags= */ 0)
Creating notifications:
Prof. Rahul Khandarkar 9
Android Programming
• Android Notification provides short, timely information about the action happened in
the application, even if it is not running.
• The notification displays the icon, title and some amount of the content text.
• The properties of Android notification are set using NotificationCompat.Builder
object.
• Some of the notification properties are mention below:
• setSmallIcon(): It sets the icon of notification.
• setContentTitle(): It is used to set the title of notification.
• setContentText(): It is used to set the text message.
• setAutoCancel(): It sets the cancelable property of notification.
• setPriority(): It sets the priority of notification.
Step 1 - Create Notification Builder
We can use Notification Builder to set various Notification properties like its small
and large icons, title, priority etc.
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
Step 2 - Setting Notification Properties
Once we have Builder object, we can set its Notification properties using Builder
object as per your requirement. But it is mandatory to set at least following −
• A small icon, set by setSmallIcon()
• A title, set by setContentTitle()
• Detail text, set by setContentText()
• mBuilder.setSmallIcon(R.drawable.notification_icon);
• mBuilder.setContentTitle("Notification Alert, Click Me!");
• mBuilder.setContentText("Hi, This is Android Notification Detail!");
Step 3 - Attach Actions
Prof. Rahul Khandarkar 10
Android Programming
• This is an optional part and required if you want to attach an action with the
notification. An action allows users to go directly from the notification to an Activity
in your application, where they can look at one or more events or do further work.
• The action is defined by a PendingIntent containing an Intent that starts an Activity
in your application. To associate the PendingIntent with a gesture, call the appropriate
method of NotificationCompat.Builder. For example, if you want to start Activity
when the user clicks the notification text in the notification drawer, you add the
PendingIntent by calling setContentIntent().
• A PendingIntent object helps you to perform an action on your applications behalf,
often at a later time, without caring of whether or not your application is running.
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder =
TaskStackBuilder.create(this);
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT)
; mBuilder.setContentIntent(resultPendingIntent);
Step 4 - Issue the notification
• Finally, you pass the Notification object to the system by calling
NotificationManager.notify() to send your notification. Make sure you call
NotificationCompat.Builder.build() method on builder object before notifying it.
This method combines all of the options that have been set and return a new
Notification object.
NotificationManager mNotificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
Prof. Rahul Khandarkar 11
Android Programming
// notificationID allows you to update the notification later on.
mNotificationManager.notify(notificationID, mBuilder.build());
Setting and customizing the notification tray UI:
• Customizing the notification tray UI in Android can be done by creating a custom
notification layout and using the NotificationCompat class to build and display the
notification. Here's a general guide to help you get started:
1. Create a Custom Layout for Notification:
• Create an XML layout file for your custom notification layout. For instance,
(custom_notification_layout.xml)
<!-- custom_notification_layout.xml -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Customize your notification layout -->
<!-- Example: TextView, ImageView, Buttons, etc. -->
</LinearLayout>
2. Build the Notification using NotificationCompat:
In your code, create a notification using NotificationCompat.Builder and set
its content view to your custom layout.
Prof. Rahul Khandarkar 12
Android Programming
// Build a Notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Title")
.setContentText("Content")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
// Create RemoteViews object and set the custom layout
RemoteViews customLayout = new RemoteViews(context.getPackageName(),
R.layout.custom_notification_layout);
builder.setCustomContentView(customLayout);
// Create the notification manager and show the notification
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(context);
notificationManager.notify(notificationId,
builder.build());
3. Handle Notification Clicks (Optional):
You might want to handle clicks on your custom notification. To do this, set a pending
intent to the notification
// Create an explicit intent for an activity in your app
Intent intent = new Intent(context, YourActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Set the content intent
builder.setContentIntent(pendingIntent);
4. Ensure Proper Permissions and Channel Setup:
Prof. Rahul Khandarkar 13
Android Programming
• Make sure you have the necessary permissions declared in the AndroidManifest.xml
and create a notification channel if targeting Android Oreo (API 26) and above.
Services in android:
• Services in Android are a special component that facilitates an application to run in the
background in order to perform long-running operation tasks.
• The prime aim of a service is to ensure that the application remains active in the
background so that the user can operate multiple applications at the same time.
• A user-interface is not desirable for android services as it is designed to operate
longrunning processes without any user intervention.
• A service can run continuously in the background even if the application is closed or
the user switches to another application.
• Further, application components can bind itself to service to carry out inter-process
communication (IPC).
• There is a major difference between android services and threads, one must not be
confused between the two
• Thread is a feature provided by the Operating system to allow the user to perform
operations in the background.
• While service is an android component that performs a long-running operation about
which the user might not be aware of as it does not have UI.
• A service needs to be declared in the AndroidManifest.xml file and the implementing
class must extend the Service class or one of its subclasses.
• The following code shows an example for a service declaration and its
implementation.
<service
Android:name=“MyService” android:icon=“@drawable/icon”
android:label=“@string/service_name”></service>
Prof. Rahul Khandarkar 14
Android Programming
public class MyService extends Service {
@Override public int onStartCommand(Intent intent, int flags,
int startId) {
//TODO do something useful return
Service.START_NOT_STICKY; }
@Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation return
null;
}
}
• An Android component (service, receiver, activity) can trigger the execution of a
service via the startService(intent) method.
// use this to start and trigger a service
Intent i= new Intent(context, MyService.class);
// potentially add data to the intent
i.putExtra("KEY1", "Value to be used by the service");
context.startService(i);
• Alternatively, you can also start a service via the bindService() method call. This
allows you to communicate directly with the service.
How to stop services:
• We can stop a service via the stopService() method.
Prof. Rahul Khandarkar 15
Android Programming
• No matter how frequently you called the startService(intent) method, one call to the
stopService() method stops the service.
• A service can terminate itself by calling the stopSelf() method. This is typically done
if the service finishes its work.
Binding services to activities:
• When an Activity is bound to a Service, it maintains a reference to the Service
instance itself, allowing you to make method calls on the running Service as you
would any other instantiated class.
• Binding is available for Activities that would benefit from a more detailed interface
with a Service. To support binding for a Service, implement the onBind method as
shown in the simple example below:
private final IBinder binder = new MyBinder();
@Override public IBinder onBind(Intent intent)
{
return binder;
public class MyBinder extends Binder
{
MyService getService()
{
return MyService.this;
}
• The connection between the Service and Activity is represented as a
ServiceConnection.
Prof. Rahul Khandarkar 16
Android Programming
• We’ll need to implement a new ServiceConnection, overriding the
onServiceConnected and onServiceDisconnectedmethods to get a reference to the
Service instance once a connection has been established.
private MyService serviceBinder; private ServiceConnection mConnection =
new ServiceConnection(){ public void onServiceConnected(ComponentName
className , IBinder service){ serviceBinder =
((MyService.MyBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
serviceBinder = null;
};
• To perform the binding, call bindService, passing in an Intent (either explicit or
implicit) that selects the Service to bind to and an instance of your new
ServiceConnection implementation, as shown in this skeleton code:
@Override public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Bind to the service
Intent bindIntent = new Intent(MyActivity.this, MyService.class);
bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);
• Once the Service has been bound, all of its public methods and properties are available
through the serviceBinder object obtained from the onServiceConnected handler.
Prof. Rahul Khandarkar 17
Android Programming
Using asynctasks to manage background processing:
• AsyncTask is an abstract class provided by Android which helps us to use the UI
thread properly.
• This class allows us to perform long/background operations and show its result on the
UI thread without having to manipulate threads.
• The AsyncTask Android class lets us sort of bind background tasks to the UI thread.
• So using this class, you can perform background operations and then publish the
results to the UI thread that updates the UI components.
• This way we won’t have to deal with threads, handlers, runnables, etc. directly
yourself.
• It’s sort of a helper class around Thread and Handler .
• Any long running operation that may block the main thread and make the app
unresponsive could be done via AsyncTask.
• Like downloading multiple files, or making HTTP requests to your server, decoding
images, etc.
• According to the documentation, AsyncTask should ideally be used for short
background operations that lasts for a few seconds at most.
• In order to use AsyncTask, we’ll have to subclass it.
class MyAsyncTask extends AsyncTask
{
@Override protected Object doInBackground(Object... params) {
// Do some background work
Log.d(TAG, "MyAsyncTask@doInBackground from another thread");
return new Object();
}
}
Prof. Rahul Khandarkar 18
Android Programming
To execute the task we’ll have to instantiate it and call execute():
new MyAsyncTask().execute();
Handler, looper and runnable:
Looper:
• Looper is a class that runs message loop for some thread.
• In Java we have threads, in which we might do some useful work.
• Initially threads don’t have an event loop capability, but we can add these capabilities
via attaching Looper to them.
• Looper has two main methods: prepare and loop.
• The first method prepare — inits thread and attaches Looper to it.
• The second method loop starts event loop.
• The last methods which are interesting to us in Looper class are quit and quitSafely.
These methods are used to stop event loop
• The second waits until all the messages are processed and then terminates, therefore it
is called safe.
• The first one is not safe as it will terminate processing the queue and some events
might be left unprocessed.
Handler:
• Handler is a class which allows you to send and handle Messages and Runnables from
thread’s MessageQueue.
• Basically it works the following way:
1. Client initializes Handler and Looper (so the whole infrastructure is now ready to use)
2. Client sends messages to Handler
3. Handler posts messages to Looper’s MessageQueue
4. Looper processes messages in MessageQueue
Prof. Rahul Khandarkar 19
Android Programming
5. When message is ready to be processed, Looper sends it back to Handler, which can
handle message.
• So, we see that Handler does two things:
1) posts messages to be placed in a queue,
2) handles messages when they were processed by Looper.
Runnable:
• Java provides the Runnable interface to identify those objects that supply code for
threads to execute via this interface's solitary public void run() method—a thread
receives no arguments and returns no value.
• Classes implement Runnable to supply this code, and one of these classes is Thread.
• Thread provides a consistent interface to the underlying operating system's threading
architecture. (The operating system is typically responsible for creating and managing
threads.)
• Thread makes it possible to associate code with threads, as well as start and manage
those threads. Each Thread instance associates with a single thread.
• Thread declares several constructors for initializing Thread objects.
• Some of these constructors take Runnable arguments: you can supply code to run
without having to extend Thread.
Prof. Rahul Khandarkar 20
Android Programming
• Other constructors do not take Runnable arguments: you must extend Thread and
override its run() method to supply the code to run.
• For example, Thread(Runnable runnable) initializes a new Thread object to the
specified runnable whose code is to be executed. In contrast, Thread() does not
initialize Thread to a Runnable argument.
• Instead, your Thread subclass provides a constructor that calls Thread(), and the
subclass also overrides Thread's run() method.
19
Prof. Manasi Talele