In Android, an application is composed of several key components that work together to create a functional and interactive app. These components manage different aspects of the application’s behavior and interaction with users and other apps.
Activities represent a single screen with a user interface. They are crucial for interacting with users and are often considered the entry points of an application.
Services run in the background to perform long-running operations or tasks without user interaction. They continue to run even if the user switches to another app.
Broadcast receivers listen for and respond to system-wide broadcast announcements or events. They handle events such as incoming calls or system changes.
Content providers manage and share app data with other applications. They provide a standard interface for data access and manipulation across different apps.
Besides the main components, there are other essential elements in Android applications that enhance functionality and user experience.
An Activity in Android is a crucial component that provides the window in which an app draws its user interface (UI). Each activity represents a single screen in an Android application, much like a window or frame in Java. The activity window typically takes up the full screen but can be resized or float over other windows in certain scenarios.
Activities allow developers to place all UI components or widgets in a single screen. Generally, each activity corresponds to one screen of the app. For example, one activity may handle a Preferences screen, while another may manage a Select Photo screen.
The Android Activity class is a subclass of ContextThemeWrapper
, meaning it
inherits the ability to apply themes and styles to its UI components.
The Android Activity Lifecycle refers to the various states that an activity can exist in as it moves between foreground and background or when it gets interrupted by another activity. These states define how an activity behaves and manages its resources. There are four main states:
The activity lifecycle is crucial for managing an Android app's resources efficiently. Understanding these states helps in designing applications that perform well under different conditions, such as interruptions or multitasking. Activities provide the foundation for user interaction by managing the screen, handling user inputs, and maintaining their states as they transition through various lifecycle stages.
A Toast is a small message that pops up on the screen for a short duration, providing feedback to the user. Unlike a dialog, a toast does not block user interaction with the app, making it useful for showing non-intrusive messages like "Task completed," "Network error," or "File saved successfully."
In Android, a Toast
message can be created and displayed using the following syntax:
Toast.makeText(context, message, duration).show();
Let’s break this down:
this
or getApplicationContext()
."Hello, World!"
.Toast.LENGTH_SHORT
: Displays the toast for a short period (~2 seconds).Toast.LENGTH_LONG
: Displays the toast for a longer period (~3.5 seconds).
Toast.makeText(this, "Hello, World!", Toast.LENGTH_SHORT).show();
Step-by-Step Explanation:
package com.example.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
Button myBtn = findViewById(R.id.button);
myBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
i = i + 1;
Toast.makeText(MainActivity.this, "No. of times button is clicked = " + i , Toast.LENGTH_SHORT).show();
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Toast Demo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.486"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.091" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#5DE063"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="0.584" />
</androidx.constraintlayout.widget.ConstraintLayout>
We already know that the Android Activity Lifecycle describes the different states an activity goes through from its creation to its destruction. Below is a sample Android program that uses Toast messages to indicate when different lifecycle methods are called. This will help you understand how activities transition through these states.
In this example, we'll implement a simple Android activity that displays a Toast message for each lifecycle method:
package com.example.lifecycleexample;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "Activity Created", Toast.LENGTH_SHORT).show();
}
@Override
protected void onStart() {
super.onStart();
Toast.makeText(this, "Activity Started", Toast.LENGTH_SHORT).show();
}
@Override
protected void onResume() {
super.onResume();
Toast.makeText(this, "Activity Resumed", Toast.LENGTH_SHORT).show();
}
@Override
protected void onPause() {
super.onPause();
Toast.makeText(this, "Activity Paused", Toast.LENGTH_SHORT).show();
}
@Override
protected void onStop() {
super.onStop();
Toast.makeText(this, "Activity Stopped", Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Activity Destroyed", Toast.LENGTH_SHORT).show();
}
}
This program demonstrates how to use Toast
messages to track the lifecycle of an Android
activity. Here’s what each lifecycle method does:
A Service in Android is a component that runs in the background to perform long-running operations without needing to interact with the user. It doesn't provide a user interface but works to:
Services are helpful for running tasks in the background, such as playing music, downloading files, or handling long-running computations.
n Android, Intents are messaging objects used to communicate between different app components. When it comes to Services, Intents are essential because:
An Intent is a messaging object that allows you to request an action from another component, such as launching an Activity, starting a Service, or delivering a broadcast. Intents can be used to communicate between different components of an application or even between applications.
An Explicit Intent directly specifies the component (usually an Activity or Service) that you want to start. This is useful when you know the class name of the component you want to interact with.
Example: Starting a new Activity within the same app.
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
In this example, MainActivity.this is the context, and SecondActivity.class is the class of the Activity we want to start.
An Implicit Intent does not specify the component to be started. Instead, it defines an action to be performed, allowing any app that can handle that action to respond. This is useful for actions that could be handled by multiple applications.
Example: Sharing content across apps.
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Hello, check this out!");
startActivity(Intent.createChooser(shareIntent, "Share via"));
In this example, Intent.ACTION_SEND indicates that we want to share some text. The setType() method specifies the type of data being shared, and putExtra() adds the actual text content. The Intent.createChooser() method presents a chooser dialog to allow the user to select an app to share with.
Understanding the Intent Class:
The Intent class in Android is used to perform operations such as starting another Activity or Service. Here’s how it works:
Creating an Intent:
To create an Intent, you typically use the following constructor:
Intent(Context context, Class<?> cls)
Example Usage of Intent:
Now that we know how to create an Intent, let’s look at an example where we use it to navigate between two activities: MainActivity and SecondActivity.
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the button in the layout
Button button = findViewById(R.id.button);
// Set an OnClickListener for the button
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Create an Explicit Intent to open SecondActivity
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent); // Start SecondActivity
}
});
}
}
package com.example.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity);
// Find the button in the layout
Button secBtn = findViewById(R.id.button2);
// Set an OnClickListener for the button
secBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Create an Explicit Intent to return to MainActivity
Intent intent = new Intent(SecondActivity.this, MainActivity.class);
startActivity(intent); // Start MainActivity
finish(); // Close SecondActivity
}
});
}
}
Explanation of the Example:
Method Breakdown:
In Android, a Service is a component that runs in the background to perform long-running operations or to perform work for remote processes. Unlike Activities, Services do not have a user interface and can continue running even if the user switches to another application. Understanding the lifecycle of a Service is crucial for managing its operations and resources effectively.
Called when the service is first created. This is where you perform one-time initialization tasks, such as setting up resources.
@Override
public void onCreate() {
super.onCreate();
// Initialization code, e.g., setting up media player
}
Called every time a client starts the service using startService()
. This method
allows the service to perform its operations.
It returns an integer that indicates how the system should handle the service if it is killed:
START_NOT_STICKY
: The service will not be recreated until an explicit
request is made.START_STICKY
: The service will be recreated, but the last intent will not
be delivered.START_REDELIVER_INTENT
: The service will be recreated, and the last intent
will be redelivered.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Code to execute when the service is started
return START_STICKY; // or START_NOT_STICKY, etc.
}
Called when a client binds to the service using bindService(). This method is used for bound services, allowing clients to interact with the service.
It must return an IBinder object. If the service is not intended to be bound, it should return null.
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null; // No binding provided
}
Called when all clients have disconnected from a particular interface published by the service. This can be used to perform cleanup if needed.
@Override
public boolean onUnbind(Intent intent) {
// Code to execute when service is unbound
return super.onUnbind(intent);
}
Called when the service is no longer used and is being destroyed. This is where you should clean up resources, such as stopping threads or releasing resources.
@Override
public void onDestroy() {
super.onDestroy();
// Cleanup code, e.g., stopping media player
}
onCreate()
is called once when the service is created.
onStartCommand()
is called every time the service is
started.onBind()
is called when a client binds to the service;
return null
if not needed.onUnbind()
is called when clients unbind from the
service.onDestroy()
is called when the service is stopped and
needs to release resources.Now that you understand Intents and how they work, let's move on to an example of using an Intent to start a Service. In this case, we will create a Service to play a default ringtone.
Step 1: Create the Service Class
package com.example.myapplication;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.provider.Settings;
import android.widget.Toast;
import androidx.annotation.Nullable;
public class MyService extends Service {
private MediaPlayer mPlayer;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null; // We don't need to bind this service
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mPlayer = MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI); // Play default ringtone
mPlayer.setLooping(true); // Loop the ringtone
mPlayer.start(); // Start playing
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId); // Call super method
}
@Override
public void onDestroy() {
super.onDestroy();
if (mPlayer != null) {
mPlayer.stop(); // Stop playing
mPlayer.release(); // Release resources
}
Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
}
}
Explanation:
MyService
class extends the Service
class.Step 2: Start and Stop the Service from an Activity
package com.example.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private Button startButton, stopButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startButton = findViewById(R.id.startButton);
stopButton = findViewById(R.id.stopButton);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent serviceIntent = new Intent(MainActivity.this, MyService.class);
startService(serviceIntent); // Start the service
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent serviceIntent = new Intent(MainActivity.this, MyService.class);
stopService(serviceIntent); // Stop the service
}
});
}
}
Explanation:
MainActivity
class is where we manage our user interface.MyService
and calls startService()
to start the service.MyService
and calls stopService()
to stop the service.Step 3: Update the Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/startServiceBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Service" />
<Button
android:id="@+id/stopServiceBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop Service"
android:layout_below="@id/startServiceBtn"
android:layout_marginTop="20dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
Explanation:
LinearLayout
with two buttons: startButton
and
stopButton
.
Step 4: Declare the Service in AndroidManifest.xml
<service android:name=".MyRingtoneService" />
Explanation:
AndroidManifest.xml
, we declare our service using
<service android:name=".MyService" />
.
Summary of the Program:
MyService
that plays a default ringtone using the
MediaPlayer
class.
MainActivity
, which uses
Intents to communicate with the Service.Step-by-Step Explanation of a Bound service
Example: Bound Service for Generating Random Numbers
package com.example.mybcaboundservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import androidx.annotation.Nullable;
import java.util.Random;
public class BoundedService extends Service {
private Random noGenerator = new Random();
public BoundedService(){}
// IBinder object to interact with the service
private IBinder myBinder = new LocalBinder();
public class LocalBinder extends Binder {
BoundedService getService(){
return BoundedService.this;
}
}
// This is where the client (Activity) binds to the service
@Nullable
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
// A method that returns a random number
public int getRandom(){
return noGenerator.nextInt(100);
}
}
package com.example.mybcaboundservice;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
BoundedService bService; // Reference to the bound service
Intent myIntent; // Intent for binding to the service
boolean bound = false; // Tracks if the service is bound
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view){
// Binding the service
myIntent = new Intent(MainActivity.this, BoundedService.class);
bindService(myIntent, sConnection, BIND_AUTO_CREATE); // Automatically create and bind service
Toast.makeText(MainActivity.this, "Service Bounded", Toast.LENGTH_SHORT).show();
}
// ServiceConnection object that manages the connection with the service
private ServiceConnection sConnection= new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
BoundedService.LocalBinder myBinder = (BoundedService.LocalBinder) iBinder;
bService = myBinder.getService(); // Get service instance
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
bound = false;
}
};
public void stop(View view){
// Unbind the service
unbindService(sConnection);
Toast.makeText(MainActivity.this, "Service UnBounded", Toast.LENGTH_SHORT).show();
bound = false;
}
public void displayNumber(View view){
if(bound){
// Use the bound service to generate a random number
int i = bService.getRandom();
Toast.makeText(MainActivity.this, "" + i, Toast.LENGTH_SHORT).show();
}
}
}
In this example:
Understanding ListView
Example: Using ArrayAdapter to Display a List of Strings
activity_main.xml
). Here's
how to
do it:
<ListView
android:id="@+id/myListXML"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/darker_gray"
android:dividerHeight="1dp" />
package com.example.mybcaadapter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
ListView myListView;
String myArr[] = {"GEHU-BHIMTAL", "GEHU-HLD", "GEHU-DDN"}; // Array of strings
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Reference the ListView from the layout
myListView = findViewById(R.id.myListXML);
// Create an ArrayAdapter to bind the data to the ListView
ArrayAdapter myAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, myArr);
myListView.setAdapter(myAdapter); // Set the adapter for the ListView
}
}
This example demonstrates how to create a ListView in Android, bind data using an ArrayAdapter, and display a simple list of items.