Download as pdf or txt
Download as pdf or txt
You are on page 1of 21

MAD - Module 3

Intents, Services and Notification


Notifications
• Is a message that Android displays outside your app's UI to provide the user with
o reminders,
o communication from other people, or
o other timely information from your app
• Users can tap the notification to open your app or take an action directly from the
notification
• Notifications appear to users in different locations and formats
o An icon in the status bar
o A more detailed entry in the notification drawer
o As a badge on the app's icon
o On paired wearable automatically
• Status bar and notification drawer
o When you issue a notification, it first appears as
an icon in the status bar
o Users can swipe down on the status bar to open
the notification drawer, where they can view
more details and take actions with the notification
o Users can drag down on a notification in the
drawer to reveal the expanded view, which shows
additional content and action buttons, if provided
o A notification remains visible in the notification
drawer until dismissed by the app or the user
• Heads-up notification
o Beginning with Android 5.0, notifications can
briefly appear in a floating window called a
heads-up notification
o This behaviour is for important notifications
that the user should know about immediately,
and it appears only if the device is unlocked
• Lock screen
o Beginning with Android 5.0, notifications can appear on the lock screen
o You can programmatically set the level of detail visible in notifications posted
by your app on a secure lock screen, or even whether the notification will
show on the lock screen at all

Intents
• Used to activate a component in an application
• Used as a message-passing mechanism
• If we want to invoke a new activity from our current activity, then we need to fire
an intent specifying the new activity
• If we want to start another application from our activity, then also we require
intent
• Intents have been classified into two types
o Explicit Intents
o Implicit Intents

Uses of Intents
1. Starting an activity:
o startActivity (Intent)
▪ The startActivity(Intent) method is used to start a new activity, which will
be placed at the top of the activity stack
▪ It takes a single argument, an Intent, which describes the activity to be
executed
o startActivityForResult (Intent, int): Used to get a result back from an activity
when it ends
2. Starting a service:
o A Service is a component that performs operations in the background without a
user interface
o With Android 5.0 (API level 21) and later, you can start a service with
JobScheduler
o For versions earlier than Android 5.0 (API level 21), you can start a service by
using methods of the Service class startService(Intent)
3. Delivering a broadcast:
o A broadcast is a message that any app can receive
o The system delivers various broadcasts for system events, such as when the
system boots up or the device starts charging
o You can deliver a broadcast to other apps by using method
sendBroadcast(Intent)

Explicit Intents
• Explicit intent is called for internal communication of an application
• It is being invoked by mentioning the target component name (like an activity)
• The component or activity can be specified which should be active on receiving the
intent
• For this reason, mostly it is used for intra application communication
• Example:
Intent i = new Intent (getApplicationContext(),
MyOtherActivity.class);
startActivity(i);
• After startActivity is called, the new Activity (in this example MyOtherActivity) will
be created and become visible and active, moving to the top of the Activity stack
• Calling finish on the new Activity, or pressing the hardware back button, will close
it and remove it from the stack.
• Alternatively, developers can navigate to the previous Activity, or yet another
Activity, by calling startActivity
• Passing Values via Explicit Intents
Intent i = new Intent(Main_Activity.this, Activity2.class);
i.putExtra("uname", username);
i.putExtra("email", emailid);
startActivity(i);
Retrieving Values in Activity 2 (snippet inside the onCreate() function)
Intent thisActivity = getIntent();
String userName = thisActivity.getStringExtra(“uname”);
String emailID = thisActivity.getStringExtra(“email”);
Implicit Intent

• It is used for inter-application communication.


• To start an Implicit Intent, specify the action which should be performed
• Then it is sent to the Android system, where it searches for all components which
are registered for the specific action and the fitting data type
• If only one component is found, Android starts this component directly
• If several components are identified by the Android system, the user will get a
selection dialog and can decide which component should be used for the intent.
(Ex: to open PDFs, we get multiple apps to choose from)
• In Implicit Intents we do need to specify the name of the component. We just
specify the Action which has to be performed and further action is handled by the
component of another application.
• Opening a webpage:
Intent siteInt = new Intent(Intent.ACTION_VIEW);
siteInt.setData(Uri.parse("https://www.google.com"));
startActivity(siteInt);
• Opening gallery:
Intent galleryInt = new Intent(Intent.ACTION_GET_CONTENT);
galleryInt.setType("image/*");
startActivity(galleryInt);
• Dial a number:
Intent dialInt = new Intent(Intent.ACTION_DIAL);
dialInt.setData(Uri.parse("tel:"+num));
startActivity(dialInt);
Native Android Actions
Native Android applications also use Intents to launch Activities and sub-Activities
1. ACTION_ANSWER: Opens an Activity that handles incoming calls
2. ACTION_CALL: Brings up a phone dialer and immediately initiates a call using the
number supplied in the Intent URI
3. ACTION_DELETE: Starts an Activity that lets you delete the data specified at the
Intent’s data URI
4. ACTION_DIAL: Brings up a dialer application with the number to dial pre-populated
from the Intent URI. By default, this is handled by the native Android phone dialer.
5. ACTION_EDIT: Requests an Activity that can edit the data at the specified Intent
URI
6. ACTION_PICK:
o Launches a sub-Activity that lets you pick an item from the Content Provider
specified by the Intent URI.
o When closed it should return a URI to the item that was picked.
o The Activity launched depends on the data being picked: for example, passing
content://contacts/people will invoke the native contacts list
7. ACTION_SEARCH: Launches the Activity used for performing a search. Supply the
search term as a string in the Intent’s extras using the SearchManager.QUERY key
8. ACTION_SENDTO: Launches an Activity to send a message to the contact specified
by the Intent URI
9. ACTION_SEND: Launches an Activity that sends the data specified in the Intent
10. ACTION_WEB_SEARCH: Opens an Activity that performs a web search based on
the text supplied in the Intent URI (typically the browser)
11. ACTION_VIEW:
o The most common generic action
o View asks that the data supplied in the Intent’ s URI be viewed in the most
reasonable manner
▪ http: addresses will open in the browser
▪ tel: addresses will open the dialer to call the number
▪ geo: addresses will be displayed in the Google Maps application
Intent Filters
• An intent filter declares the capabilities of its parent component — what an
activity or service can do and what types of broadcasts a receiver can handle.
• It opens the component to receiving intents of the advertised type, while filtering
out those that are not meaningful for the component.
• Intent filters are declared in the Android manifest file.
• Intent filter must contain <action>
• It is an expression in an app's manifest file that specifies the type of intents that
the component would like to receive.
• For instance, by declaring an intent filter for an activity, you make it possible for
other apps to directly start your activity with a certain kind of intent.
• Using Intent Filters, application components declare that they can respond to
action requests from any application installed on the device
• Most of the intent filter are described by the following tags:
o <action>,
o <category>
o <data>
Syntax of Intent Filters
• Intent filter is declared inside Manifest file for an Activity.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
The above intent filter declares that MainActivity should be the first activity to be
launched when there are more than 1 activities are used in the application.

Elements In Intent Filter


1. <action>
• Uses the android:name attribute to specify the name of the action being serviced
• Each Intent Filter must have one (and only one) action tag
• Actions should be unique strings that are self-describing
2. <category>
• Uses the android:name attribute to specify under which circumstances the action
should be serviced
• Each Intent Filter tag can include multiple category tags
• You can specify your own categories or use the standard values provided by
Android and listed here:
o DEFAULT:
▪ Set this to make a component the default action for the data type specified in
the Intent Filter
▪ This is also necessary for Activities that are launched using an explicit Intent
o ALTERNATIVE:
▪ This category specifies that this action should be available as an alternative to
the default action performed on an item of this data type
▪ Example, where the default action for a contact is to view it, the alternative
could be to edit it
o HOME
▪ By setting an Intent Filter category as home without specifying an action, you
are presenting it as an alternative to the native home screen
o LAUNCHER
▪ Using this category makes an Activity appear in the application launcher
3. <data>
• The data tag lets you specify which data types your component can act on
• You can include several data tags as appropriate
• You can use any combination of the following attributes to specify the data your
component supports:
o android:host - Specifies a valid hostname (e.g., google.com)
o android:mimetype - Lets you specify the type of data your component is
capable of handling
o android:path - Specifies valid path values for the URI (/et.gr.a,nsport/boats/)
o android:port - Specifies valid ports for the specified host
o android:scheme - Requires a particular scheme (e.g., content or http)
Example of Intent Filter:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.menuapplication">

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name=
"android.intent.action.MAIN"/>
<category android:name=
"android.intent.category.LAUNCHER"/>
</intent-filter>

<intent-filter>
<action android:name=
"android.intent.action.SEND"/>
<category android:name=
"android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>

<intent-filter>
<action android:name=
"android.intent.action.VIEW"/>
<category android:name=
"android.intent.category.DEFAULT"/>
<category android:name=
"android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
</intent-filter>
</activity>
</application>
</manifest>

Services
• Android service is a component that is used to perform operations on the
background such as playing music, handle network transactions, interacting
content providers etc
• It doesn't have any UI
• Services run in the background — updating your Content Providers, firing Intents,
and triggering Notifications
• They are the perfect means of performing ongoing or regular processing and of
handling events even when your application’s Activities are invisible or inactive,
or have been closed
• Services are started, stopped, and controlled from other application components,
including other Services, Activities, and Broadcast Receivers

Implementing a Service
• To define a Service, create a new class that extends Service
• You’ll need to override onBind and onCreate
• Skeleton of implementation:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service {
@Override
public void onCreate() {
// TODO: Actions to perform when service is created.
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Replace with service binding implementation.
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Launch a background thread to do processing.
return Service.START_STICKY;
}
}
• Services are launched on the main Application thread
• The standard pattern for implementing a Service is to create and run a new thread
from onStartCommand() to perform the processing in the background and stop
the Service when it’s complete
• This pattern lets onStartCommand() complete quickly, and lets you control the
restart behavior using one of the following Service constants:
o START_STICKY: If you return this value, onStartCommand() will be called
every time your Service restarts after being terminated by the run time.
o START_NOT_STICKY: This mode is used for Services that are started to
process specific actions or commands and need to be restarted after being
terminated by the run time.
• To start a Service explicitly, call startService. Ex:
startService(new Intent(this, myService.class));
• To stop a service. Ex:
stopService(new Intent(this, service.getClass()));

Service Lifecycle
• The lifecycle of service can follow two different paths:
o Started
o Bound
• Started/Unbounded Service :
o A service is started when component (like activity) calls startService() method
o It runs in the background indefinitely
o The service can stop itself by calling the stopSelf() method
• Bound Service :
o A service is bound when another component (e.g. client) calls bindService()
o The client can unbind the service by calling the unbindService() method
o The service cannot be stopped until all clients unbind the service
Service Lifecycle
• onCreate():
o Executed when the service is first created in order to set up the initial
configurations you might need.
o This method is executed only if the service is not already running.
• onStartCommand():
o Executed every time startService() is invoked by another component, like an
Activity or a BroadcastReceiver.
o When you use this method, the Service will run until you call stopSelf() or
stopService()
• onBind():
o Executed when a component calls bindService() and returns an instance of
IBinder, providing a communication channel to the Service.
o A call to bindService() will keep the service running as long as there are
clients bound to it.
If the service is bound, the active lifetime ends when onUnbind() returns.
• onUnbind(): Called when all clients have disconnected from a particular interface
published by the service.
A started service is stopped by a call to either stopSelf() or stopService()
• stopSelf() / stopService(): Stops the service, if it was previously started.
• onDestroy(): Executed when the service is no longer in use and allows for disposal
of resources that have been allocated.

Unbound Service vs Bound Service


Unbound Service Bound Service
Used for performing long, repetitive Used for performing background tasks
tasks that are in bound with another
component (like an activity / Broad. Rec.)
The Unbound service runs in the The Bound service does not run in the
background indefinitely. background indefinitely.
It is started by calling startService(). It is started by calling bindService().
Once an Unbound Service is started, it • Bound Service runs as long as the
runs indefinitely until service is bound to a client.
• Application component calls • Clients unbind using unbindService()
stopService() method • When there is no active client bound
• Service itself calls SelfStop() method. with the service, onUnbind() is invoked
Unbound Service is independent of the Bound Service is dependent on the
component in which it was started component(s) which started it.
Application: If you want to update the Application: If you want to see the
location in your activity when you move coordinates of your current location
every 10 meters when you click some button in the
activity.
Example: Downloading a file, playing Example: Setting an alarm: the service
music: once the music player has been runs in the background until the alarm
started, it runs in the background, even app unbinds itself when the set alarm is
when the user is using other apps. It only triggered.
stops when the user explicitly stops it.
Broadcast Receiver
• It simply responds to broadcast messages (events or intents) from other
applications or from the system itself
• It is an android component which allows you to register for system or application
events
• All registered receivers for an event are notified by the Android runtime once this
event happens

• Apps also send custom broadcasts, for example, to notify other apps of something
that they might be interested in (Ex: some new data has been downloaded)
• Ex: when the system switches in and out of airplane mode. System broadcasts are
sent to all apps that are subscribed to receive the events.
• Steps to make Broadcast Receiver works for the system
o Creating the Broadcast Receiver
o Registering Broadcast Receiver

Creating the Broadcast Receiver


• A broadcast receiver is implemented as a subclass of BroadcastReceiver class
• Override the onReceive() method where each message is received as an Intent
object parameter
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
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
<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"/>
</intent-filter>
</receiver>
</application>

Broadcast Events

Event constant Description

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 broadcasted 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 The device reboots.

Async Task
• AsyncTask (Asynchronous Task) allows us to run the instruction in the background
and then synchronize again with our main thread.
• AsyncTask must be subclassed to be used. The subclass will override at least one
method doInBackground(Params), and most often will override a second one
onPostExecute(Result).
• AsyncTask class is used to do background operations that will update the UI.
• Used mainly for short operations.
AsyncTask Workflow:
o AsyncTask is executed using onPreExecute().
o Then, onPreExecute() calls doInBackground() for background processes
o Then, doInBackground() calls onPostExecute() method to update the UI.

• onPreExecute():
o It is invoked on the UI thread before the task is executed.
o This step is normally used to setup the task, for instance by showing a
progress bar in the user interface
• doInBackground():
o It is invoked on the background thread immediately after onPreExecute()
finishes executing.
o This step is used to perform background computation that can take a long
time. The parameters of the asynchronous task are passed to this step.
• onProgressUpdate():
o This method is used to display any form of progress in the user interface
while the background computation is still executing.
o Ex: it can be used to animate a progress bar or show logs in a text field.
• onPostExecute():
o It is invoked on the UI thread after the background computation finishes.
o The result of the background computation is passed to this step as a
parameter.

Need for Async Task


• By default, our application code runs in our main thread and every statement is
therefore executed in a sequence.
• To perform long tasks/operations, our main thread will have to be blocked until
the corresponding operation has finished.
• To provide a good user experience in our application, we need to use AsyncTask
class that runs these operations in a separate thread.

Syntax of AsyncTask
• To use AsyncTask you must subclass it. The parameters are the following
AsyncTask <TypeOfVarArgParams, ProgressValue, ResultValue>
o TypeOfVarArgParams: It is the type of the parameters sent to the task upon
execution.
o ProgressValue: It is the type of the progress units published during the
background computation.
o ResultValue: It is the type of result of the background computation.
• Skeleton example:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

protected Long doInBackground(URL... urls) {


// code that will run in the background
}

protected void onProgressUpdate(Integer... progress) {


// receive progress updates from doInBackground
}
protected void onPostExecute(Long result) {
// update the UI after background processes completes
}
}

Designing for Every Screen Size and Density


• To provide a great user experience on all Android devices, it’s important to create
your UIs knowing that your applications can run on a broad variety of screen
resolutions and physical screen sizes.
• In practice, this means that just as with websites and desktop applications, you
must design and build your applications with the expectation that they can run an
infinitely varied set of devices.
• The following sections begin by describing the range of screens you need to
consider, and how to support them, before summarizing some of the best
practices to ensure your applications are resolution- and density-independent, and
optimized for different screen sizes and layouts.

Resolution Independence
• A display’s pixel density is calculated as a function of the physical screen size and
resolution, referring to the number of physical pixels on a display relative to the
physical size of that display.
• It’s typically measured in dots per inch (dpi).
• Using Density-Independent Pixels
o As a result of the variations in screen size and resolution for Android devices,
the same number of pixels can correspond to different physical sizes on
different devices based on the screen’s DPI.
o This makes it impossible to create consistent layouts by specifying pixels.
o Instead, Android uses density-independent pixels (dp) to
▪ specify screen dimensions that
▪ scale to appear the same on screens of the same size
▪ but which use different pixel densities.
o In addition to dp units, Android also uses a scale-independent pixel (sp) for
the special case of font sizes.
• Resource Qualifiers for Pixel Density
o Scaling bitmap images can result in either
▪ lost detail (when scaling downward) or
▪ pixilation (when scaling upward).
o To ensure that your UI is crisp, clear, and devoid of probelms, it’s good
practice to include multiple image assets for different pixel densities.
o For simple types of images (usually icons), you can avoid creating separate
images for each density by using vector graphics.
o Because vector graphics define the illustration with geometric line paths
instead of pixels, they can be drawn at any size without scaling problems.
o When using Drawable resources that cannot be dynamically scaled well,
you should create and include image assets optimized for each pixel density
category:

res/drawable-ldpi Low-density resources for screens approximately 120dpi

res/drawable-mdpi Medium-density resources for screens approximately 160pi

res/drawable-tvdpi Medium to high density resources for screens approximately


213dpi

res/drawable-hdpi High-density resources for screens approximately 240dpi

res/drawable-xhdpi Extra-high-density resources for screens approximately 320dpi

Supporting and Optimizing for Different Screen Sizes


• Android devices can come in all shapes and sizes, so when designing your UI,
it’s important to ensure that your layouts not only support different screen sizes,
orientations, and aspect ratios, but also that they are optimized for each.
• It’s neither possible nor desirable to create a different absolute layout for
each specific screen configuration; instead, it’s best practice to take a two-phased
approach:
o Ensure that all your layouts are capable of scaling within a reasonable set of
bounds.
o Create a set of alternative layouts whose bounds overlap such that all
possible screen configurations are considered
Creating Scalable Layouts
• The layout managers provided by the framework are designed to support the
implementation of UIs that scale to fi t the available space.
• In all cases, you should avoid defining the location of your layout elements in
absolute terms.
• Instead, you can define the height and width of Views using
wrap_content or match_parent attributes, as appropriate.
• The wrap_content flag enables the View to define its size based on the amount
of space potentially available to it.
• The match_parent flag enables the element to expand as necessary to fill the
available space.
• Using the Linear Layout, you can create layouts represented by simple columns
or rows that fill the available width or height of the screen, respectively.
• The Relative Layout is a flexible alternative that enables you to define the
position of each UI element relative to the parent Activity and the other
elements used within the layout.

Create Alternative Layouts


• Although your layout should always respond to different screen sizes by
stretching the space within and around its views, that might not provide the
best user experience for every screen size.
• For example, the UI you designed for a phone, probably doesn't offer a good
experience on a tablet.
• Therefore, your app should also provide alternative layout resources to optimize
the UI design for certain screen sizes.
• You can provide screen-specific layouts by creating additional res/layout/
directories—one for each screen configuration that requires a different layout—
and then append a screen configuration qualifier to the layout directory name
(such as layout-w600dp for screens that have 600dp of available width).
• These configuration qualifiers represent the visible screen space available
• The system takes into account any system decorations (like the navigation bar)
and window configuration changes (such as when the user enables multi-
window mode) when selecting the layout from your app.
• Use the Smallest Width qualifier
o The "smallest width" screen size qualifier allows you to provide alternative
layouts for screens that have a certain minimum width measured in
density-independent pixels (dp or dip).
o By describing the screen size as a measure of dip, Android allows you to
create layouts that are designed for very specific screen dimensions while
avoiding any concerns you might have about different pixel densities.
o For example, you can create a layout named main_activity that's
optimized for handsets and tablets by creating different versions of the file
in directories as follows:

res/layout/main_activity.xml
# For handsets (smaller than 600dp available width)

res/layout-sw600dp/main_activity.xml
# For 7” tablets (600dp wide and bigger)

o The smallest width qualifier specifies the smallest of the screen's two
sides (height and width), regardless of the device's current orientation, so
it's a simple way to specify the overall screen size available for your layout.
• Use the Available Width qualifier
o Instead of changing the layout based on the smallest width of the screen,
you might want to change your layout based on how much
width or height is currently available.
o Ex: if you have a two-pane layout, you might want to use that, whenever
the screen provides at least 600dp of width, which might change
depending on whether the device is in landscape or portrait orientation.
o In this case, you should use the "available width" qualifier as follows:

res/layout/main_activity.xml
# For handsets (smaller than 600dp available width)

res/layout-w600dp/main_activity.xml
# For 7” tablets or any screen with 600dp available width
o If the available height is a concern for you, then you can do the same using
the "available height" qualifier.
o For example, layout-h600dp for screens with at least 600dp of screen
height.
• Add orientation qualifiers
o Although you may be able to support all size variations using only
combinations of the "smallest width" and "available width" qualifiers, you
might also want to change the user experience when the user switches
between portrait and landscape orientations.
o For that you can add the port or land qualifiers to your resource directory
names. Just be sure these come after the other size qualifiers.
For example:

res/layout/main_activity.xml
# For handsets

res/layout-land/main_activity.xml
# For handsets in landscape

res/layout-sw600dp/main_activity.xml
# For 7” tablets

res/layout-sw600dp-land/main_activity.xml
# For 7” tablets in landscape

You might also like