Android App Components
Table of Contents
What is an App Components
App components are the essential building blocks of an Android app. Each component is an entry point through which the system or a user can enter your app.
Types of app components
In Android development, there are four main components that are essential in creating an app.
Activities
- An Activity is a single screen that the user interacts with. It represents the presentation layer in Android (UI).
- Activity class provides the interface between the application and the screen.
- It also provides a set of pre-defined methods, which are triggered at different app states, and are overridden to perform anything as desired.
In simple terms, an activity is a screen that appears when we open an application and we navigate from one activity to another by clicking on buttons.
It is the activity that we interact with when we open our application. suppose you share the contact number with your friends then you click on share and it will navigate you to WhatsApp (another activity). An application has at least one activity.
To declare your activity, open your manifest file and add an <activity> element as a child of the <application> element.
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
The only required attribute for this element is android:name, which specifies the class name of the activity. You can also add attributes that define activity characteristics such as label, icon, or UI theme. For more information about these and other attributes, see the <activity> element reference documentation.
Declare permissions
You can use the manifest’s <activity>
tag to control which apps can start a particular activity. A parent activity cannot launch a child activity unless both activities have the same permissions in their manifest. If you declare a <uses-permission>
element for a parent activity, each child activity must have a matching <uses-permission>
element.
<manifest>
<activity android:name="...."
android:permission=”com.google.socialapp.permission.SHARE_POST”
/>
Then, to be allowed to call SocialApp, your app must match the permission set in SocialApp’s manifest:
<manifest>
<uses-permission android:name="com.google.socialapp.permission.SHARE_POST" />
</manifest>
For more information on permissions and security in general, see Security and Permissions.
Activity lifecycle and callbacks
The Activity lifecycle in Android represents the various states an activity goes through during its lifetime, from creation to destruction.
To navigate transitions between stages of the activity lifecycle, the Activity
class provides a core set of six callbacks: onCreate()
, onStart()
, onResume()
, onPause()
, onStop()
, and onDestroy()
. The system invokes each of these callbacks as the activity enters a new state.
onCreate()
When we open the app the onCreate() method is first called. The onCreate() method is the first callback method fired when an activity is created for the first time.
Upon creation, the activity enters into the Created state.
If there is an application start-up logic that is to be performed only once at the start of the activity life cycle, that logic can be written in the onCreate() method.
Your implementation should initialize the essential components of your activity: For example, your app should create views and bind data to lists here. Most importantly, this is where you must call setContentView()
to define the layout for the activity’s user interface.
When onCreate()
finishes, the next callback is always onStart()
.
onStart()
As onCreate()
exits, the activity enters the Started state, and the activity becomes visible to the user. It takes less time to execute.
This callback contains what amounts to the activity’s final preparations for coming to the foreground and becoming interactive.
onResume()
The system invokes this callback just before the activity starts interacting with the user. At this point, the activity is at the top of the activity stack and captures all user input. Most of an app’s core functionality is implemented in the onResume()
method.
The onResume() callback method is invoked when an activity enters into the Resumed state.
In this state, the activity interacts with the user and allows the user to view the design and functionality of an application on the screen.
The app stays in the resumed state until another activity with higher priority takes the focus. For example, receiving a phone call, the screen being turned off, and so on.
The onPause()
callback always follows onResume()
.
In case of any interruption when in the resumed state, the activity enters into the Paused state by invoking the onPause() method.
Once the activity returns from the Paused state to the Resumed state, the onResume() method is called again. Hence, the onResume() method should be implemented to initialize the components that were released on invoking onPause().
onPause()
The system calls onPause()
when the activity loses focus and enters a Paused state. This state occurs when, for example, the user taps the Back or Recents button.
When the system calls onPause()
for your activity, it technically means your activity is still partially visible, but most often is an indication that the user is leaving the activity, and the activity will soon enter the Stopped or Resumed state.
An activity in the Paused state may continue to update the UI if the user is expecting the UI to update. Examples of such an activity include one showing a navigation map screen or a media player playing. Even if such activities lose focus, the user expects their UI to continue updating.
You should not use onPause()
to save application or user data, make network calls, or execute database transactions. For information about saving data, see Saving and restoring activity state.
Once onPause()
finishes executing, the next callback is either onStop()
or onResume()
, depending on what happens after the activity enters the Paused state.
onStop()
The system calls onStop()
when the activity is no longer visible to the user and then the activity enters into the Stopped State.
This may happen because the activity is being destroyed, a new activity is starting, or an existing activity is entering a Resumed state and is covering the stopped activity. In all of these cases, the stopped activity is no longer visible at all.
When an activity is minimized, the onPause() callback is immediately called, and after a few milliseconds, onStop() will be called. onStop() will stop the API calls of the application.
The onStop() method is particularly useful for releasing the app resources that are no longer needed.
The next callback that the system calls is either onRestart()
, if the activity is coming back to interact with the user, or by onDestroy()
if this activity is completely terminating.
onRestart()
The system invokes this callback when an activity in the Stopped state is about to restart.
onRestart()
restores the state of the activity from the time that it was stopped.
This callback is always followed by onStart()
.
onDestroy()
The onDestroy() method is the final callback method and is invoked before an activity is destroyed.
An activity is destroyed under the following circumstances:
- The activity is finishing(or open new app)
- The system is temporarily d
- estroying the current instance of the activity to save space(When ram is full or we are not used app for long time)
onDestroy()
is usually implemented to ensure that all of an activity’s resources are released when the activity, or the process containing it, is destroyed. (resources that are not released by the onStop(), etc.)
If we have to manually destroy the app then used finish () method.
For more details see The Activity Lifecycle.
Broadcast Receiver
Android apps can send or receive broadcast messages from the Android system(Android OS) and other Android apps.
“What does the term “broadcast” mean?”
In the context of Android or other operating systems, a “broadcast” is a system-wide message or notification that can be picked up by multiple applications or components.
So, how can we receive a “broadcast”?
The answer lies in using a “broadcast receiver”. In simple terms,
A “broadcast receiver” is a component that responds to broadcast messages received from other apps or the Android operating system itself.
Examples,
When an Android device is fully booted up, What will Android system do, it sends a broadcast to all the apps that are registered to receive the “boot completion” broadcast. So that the apps can be reacted on that when the device boots up.
another example is if you have a music player app and your Android device receives an incoming call, then phone call app sends a broadcast so other apps can react to it and prioritize their operations.In the case of the music player app, once it receives the incoming call broadcast, it will pause the music.
Receiving broadcasts
Apps can receive broadcasts in two ways: through manifest-declared receivers and context-registered receivers.
Manifest-declared receivers(Static Registration)
If you declare a broadcast receiver in your manifest, the system launches your app (if the app is not already running) when the broadcast is sent.
To declare a broadcast receiver in the manifest, perform the following steps:
- Specify the
<receiver>
element in your app’s manifest.
<!-- If this receiver listens for broadcasts sent from the system or from
other apps, even other apps that you own, set android:exported to "true". -->
<receiver android:name=".MyBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
The intent filters specify the broadcast actions your receiver subscribes to.
2. Subclass BroadcastReceiver
and implement onReceive(Context, Intent)
.
private const val TAG = MyBroadcastReceiver::class.java.canonicalName
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if(intent.action==android.intent.action.BOOT_COMPLETED){
Log.d(TAG,"Boot Completion broadcast recieved."
}
}
}
}
The broadcast receiver in the example logs the given message on BOOT_COMPLETED.
Context-registered receivers(Dynamic Registration (in an Activity or Service))
Context-registered receivers receive broadcasts as long as their registering context is valid. For an example, if you register within an Activity
context, you receive broadcasts as long as the activity is not destroyed. If you register with the Application context, you receive broadcasts as long as the app is running.
To register a receiver with a context, perform the following steps:
1.In your app’s module-level build file, include version 1.9.0 or higher of the AndroidX Core library
2.Create an instance of BroadcastReceiver
:
val br: BroadcastReceiver = MyBroadcastReceiver()
3.Create an instance of IntentFilter
:
val filter = IntentFilter("android.intent.action.BOOT_COMPLETED")
4.Choose whether the broadcast receiver should be exported and visible to other apps on the device.
If this receiver is listening for broadcasts sent from the system or from other apps—even other apps that you own—use the RECEIVER_EXPORTED
flag. If instead this receiver is listening only for broadcasts sent by your app, use the RECEIVER_NOT_EXPORTED
flag.
val listenToBroadcastsFromOtherApps = false
val receiverFlags = if (listenToBroadcastsFromOtherApps) {
ContextCompat.RECEIVER_EXPORTED
} else {
ContextCompat.RECEIVER_NOT_EXPORTED
}
5. Register the receiver by calling registerReceiver()
:
ContextCompat.registerReceiver(context, br, filter, receiverFlags)
6. To stop receiving broadcasts, call unregisterReceiver(android.content.BroadcastReceiver)
. Be sure to unregister the receiver when you no longer need it or the context is no longer valid.
- Be mindful of where you register and unregister the receiver, for example, if you register a receiver in
onCreate(Bundle)
using the activity’s context, you should unregister it inonDestroy()
to prevent leaking the receiver out of the activity context. - If you register a receiver in
onResume()
, you should unregister it inonPause()
to prevent registering it multiple times (If you don’t want to receive broadcasts when paused, and this can cut down on unnecessary system overhead). - Do not unregister in
onSaveInstanceState(Bundle)
, because this isn’t called if the user moves back in the history stack.
Sending broadcasts
Android provides two ways for apps to send broadcasts:
- The
sendOrderedBroadcast(Intent, String)
method sends broadcasts to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won’t 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. - The
sendBroadcast(Intent)
method sends broadcasts to all receivers in an undefined order. This is called a Normal Broadcast. This is more efficient, but means that receivers cannot read results from other receivers, propagate data received from the broadcast, or abort the broadcast.
The following code snippet demonstrates how to send a broadcast by creating an Intent and calling sendBroadcast(Intent)
.
Intent().also { intent ->
intent.setAction("com.example.broadcast.MY_NOTIFICATION")
intent.putExtra("data", "Nothing to see here, move along.")
sendBroadcast(intent)
}
Restricting broadcasts with permissions
Permissions allow you to restrict broadcasts to the set of apps that hold certain permissions. You can enforce restrictions on either the sender or receiver of a broadcast.
Sending with permissions
When you call sendBroadcast(Intent, String)
or sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
, you can specify a permission parameter. Only receivers who have requested that permission with the tag in their manifest (and subsequently been granted the permission if it is dangerous) can receive the broadcast. For example, the following code sends a broadcast:
sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND),
Manifest.permission.BLUETOOTH_CONNECT)
To receive the broadcast, the receiving app must request the permission as shown below:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Receiving with permissions
If you specify a permission parameter when registering a broadcast receiver (either with registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
or in <receiver>
tag in your manifest), then only broadcasters who have requested the permission with the <uses-permission>
tag in their manifest (and subsequently been granted the permission if it is dangerous) can send an Intent to the receiver.
For example, assume your receiving app has a manifest-declared receiver as shown below:
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
Or your receiving app has a context-registered receiver as shown below:
Then, to be able to send broadcasts to those receivers, the sending app must request permission as shown below:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
For details check out Broadcasts overview | Android Developers.
Content Provider
In the bustling world of Android development, efficient data management and secure sharing between apps stand as pivotal pillars for creating robust and interconnected applications.
Enter Content Providers, Content providers can help an application manage access to data stored by itself or stored by other apps and provide a way to share data with other apps. They encapsulate the data and provide mechanisms for defining data security.
A content provider is an app component that manages access to a central data repository.
Providers and provider clients, together, offer a consistent, standard interface to data that also covers inter-process communication and secure data access.
You can use a content provider to abstract away the details for accessing different data sources in your application.
The Android framework includes content providers that manage data such as audio, video, images, and personal contact information. Some of these are documented in the reference documentation for the android.provider package. These providers can be accessed by any Android application, with some restriction.
Content providers allow you to manage access to a variety of data storage sources, including both structured data such as SQLite relational databases and unstructured data such as image files. For more information about the storage types available on Android, see Data and file storage overview and Data storage design.
Advantages:
Data Abstraction and Encapsulation: They enable abstraction and encapsulation of data, allowing apps to expose their data while hiding the underlying complexities, such as database schema or file storage, ensuring data integrity and security.
Security and Permissions: Content providers allow developers to define granular permissions (read/write) for different parts of the data, ensuring data security and privacy. Other apps can access only the data for which they have the appropriate permissions.
The following topics describe content providers in more detail:
- How to access and update data using an existing content provider.
- How to design and implement your own content provider.
- How to access the Calendar Provider that is part of the Android platform.
- How to access the Contacts Provider that is part of the Android platform.
Services
A service is an app component that can execute long-running activities in the background without a user interface.
A random app component can start a service, and even if the user switches to another application, the service will continue running in the background.
Additionally, a component can bind to a service to interact with it and perform Interprocess Communication (IPC).For example, a service can play music, handle network transactions, interact with a content provider, perform file I/O, and so on, all from the background.
Types of Services
These are the three different types of services:
Foreground
A foreground service performs some operation that is noticeable to the user.
For example, an audio app would use a foreground service to play an audio track. Foreground services must display a Notification. Foreground services continue running even when the user isn’t interacting with the app.
When you use a foreground service, you must display a notification so that users are actively aware that the service is running. This notification cannot be dismissed unless the service is either stopped or removed from the foreground.
Learn more about how to configure foreground services in your app.
Background
A background service performs an operation that isn’t directly noticed by the user. For example, if an app used a service to compact its storage, that would usually be a background service.
Bound
A service is bound when an app component binds to it by calling bindService()
A bound service offers a client-server interface that allows components to interact with the service, send requests, receive results, and even do so across processes with interprocess communication (IPC).
A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
Implementing a Started Service in Android
1. Create the Service Class:
Start by creating a new Kotlin class that extends the Service
class. Override the onCreate()
and onStartCommand()
methods.
A started service is one that another component starts by calling startService()
, which results in a call to the service’s onStartCommand()
method.
class LocalService : Service() {
private var serviceLooper: Looper? = null
private var serviceHandler: ServiceHandler? = null
override fun onCreate() {
// Perform initialization tasks here (if needed)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show()
// If we get killed, after returning from here, restart
return START_STICKY
}
override fun onBind(intent: Intent): IBinder? {
// We don't provide binding, so return null
return null
}
override fun onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show()
}
}
Notice that the onStartCommand()
method must return an integer. The integer is a value that describes how the system should continue the service in the event that the system kills it. The return value from onStartCommand()
must be one of the following constants:
- The service won’t be automatically restarted if it’s killed after
onStartCommand(
) unless there are pending intents to deliver. - This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
- If the service is killed, it will be restarted by the system. However, the
Intent
passed toonStartCommand()
will be null unless there are pending intents to start the service. - In that case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands but are running indefinitely and waiting for a job.
- If the service is killed, it will be restarted and receive the last delivered Intent, ensuring that the ongoing task can resume from where it left off.
- Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.
2.Declare the Service in the Manifest
You must declare all services in your application’s manifest file, just as you do for activities and other components.
<manifest ... >
...
<application ... >
<service android:name=".LocalService" />
...
</application>
</manifest>
You can ensure that your service is available to only your app by including the android:exported
attribute and setting it to false
. This effectively stops other apps from starting your service, even when using an explicit intent.
3. Start the Service from an Activity or Other app Component:
You can start a service from an activity or other app component by passing an Intent
to startService()
or startForegroundService()
startService(Intent(this, LocalService::class.java))
4.Implementing the lifecycle callbacks
In your implementation, you must override some callback methods that handle key aspects of the service lifecycle and provide a mechanism that allows the components to bind to the service, if appropriate. These are the most important callback methods that you should override:
The system invokes this method by calling startService()
when another component (such as an activity) requests that the service be started. When this method executes, the service is started and can run in the background indefinitely.
If you implement this, it is your responsibility to stop the service when its work is complete by calling stopSelf()
or stopService()
. If you only want to provide binding, you don’t need to implement this method.
The system invokes this method by calling bindService()
when another component wants to bind with the service (such as to perform RPC).
In your implementation of this method, you must provide an interface that clients use to communicate with the service by returning an IBinder
.
You must always implement this method; however, if you don’t want to allow binding, you should return null.
The system invokes this method to perform one-time setup procedures when the service is initially created (before it calls either onStartCommand()
or onBind()
).
If the service is already running, this method is not called.
The system invokes this method when the service is no longer used and is being destroyed. Your service should implement this to clean up any resources such as threads, registered listeners, or receivers. This is the last call that the service receives.
Stopping a service
A started service must manage its own lifecycle. That is, the system doesn’t stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand()
returns. The service must stop itself by calling stopSelf()
, or another component can stop it by calling stopService()
.
Once requested to stop with stopSelf()
or stopService()
, the system destroys the service as soon as possible
For more details check out Services overview | Android Developers.
There are also other architectural components and concepts like fragments, views, intents, and more that are crucial in Android development, contributing to the overall structure, user interface, and behavior of an app.
5.Fragments
Fragments represent a portion of a user interface or behavior within an activity. They are reusable components that can be combined within a single activity to build a multi-pane UI, especially useful for larger screens like tablets.
6.Intent
Intents are messaging objects that allow components to request functionalities from other components within the app or even from different apps. They can be used to start activities, services, or broadcast messages.
7.Views/Layouts:
Views are the basic building blocks of Android UI. They represent the UI components such as buttons, text fields, etc. Layouts, on the other hand, are containers that control the positioning of views and help in defining the UI structure.
Check this to understand in details Android Views and ViewGroups.
[…] Android App Components to know Services in […]
[…] Know more about Android application component. […]