Back to Course
Components

Android App Components — Activities, Services, Broadcast Receivers, Content Providers

Every Android application is built using four essential components that serve as the building blocks of the app. These components define how the app interacts with the user, runs background tasks, responds to system events, and shares data. Understanding these components is the foundation of Android development.

Production Reality: Every Android app must declare all its components in the AndroidManifest.xml file. Without proper declaration, components won't work. This is one of the most common mistakes beginners make.

1. Overview of the Four Components

ComponentPurposeEntry Point
ActivityUser interface screenLauncher icon or intent
ServiceBackground operationsStartService() or bindService()
Broadcast ReceiverRespond to system eventsSystem broadcasts or sendBroadcast()
Content ProviderShare data between appsContentResolver queries
Key Insight: Activities and Services are the most commonly used components. Broadcast Receivers and Content Providers are used for system-level interactions and data sharing. Every app has at least one Activity.

2. Activity — The User Interface

An Activity is a single, focused screen that the user can interact with. It provides a window for drawing the UI and handling user interactions. Almost every screen in your app will be an Activity.

Activity Lifecycle

Activities have a well-defined lifecycle managed by the Android system. Understanding this lifecycle is critical to building robust apps.

Activity Lifecycle
┌─────────────────────────────────────────────────────────────┐
│ Activity Launched │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ onCreate() → Called when Activity is first created │
│ → Initialize UI, bind data │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ onStart() → Activity becomes visible │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ onResume() → Activity is in the foreground │
│ → User can interact │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ Activity is running (foreground) │
└─────────────────────────────────────────────────────────────┘

┌────────────┴────────────┐
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ onPause() │ │ onDestroy() │
│ → Activity partially │ │ → Activity is being │
│ visible │ │ destroyed │
│ → Save user data │ │ → Clean up resources │
└─────────────────────────┘ └─────────────────────────┘
│ │
▼ │
┌─────────────────────────┐ │
│ onStop() │ │
│ → Activity no longer │ │
│ visible │ │
└─────────────────────────┘ │
│ │
▼ │
┌─────────────────────────┐ │
│ onRestart() │ │
│ → Activity restarting │ │
│ after being stopped │ │
└─────────────────────────┘ │
│ │
└────────────┬────────────┘

┌─────────────────────────────────────────────────────────────┐
│ Activity is destroyed │
└─────────────────────────────────────────────────────────────┘

Activity Lifecycle Methods

MethodWhen CalledWhat to Do
onCreate()Activity first createdInitialize UI, set content view, bind data
onStart()Activity becomes visiblePrepare UI for user interaction
onResume()Activity in foregroundStart animations, camera, GPS
onPause()Activity partially obscuredSave user data, stop animations
onStop()Activity no longer visibleRelease resources, stop heavy operations
onRestart()Activity restarting after stopRe-initialize resources
onDestroy()Activity being destroyedClean up all resources

Basic Activity Implementation

// MainActivity.kt
package com.example.myapp

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Initialize UI elements
        val button = findViewById<android.widget.Button>(R.id.myButton)
        button.setOnClickListener {
            Toast.makeText(this, "Button Clicked!", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onStart() {
        super.onStart()
        // Activity becomes visible
    }

    override fun onResume() {
        super.onResume()
        // Activity is in foreground
    }

    override fun onPause() {
        super.onPause()
        // Save user data here
    }

    override fun onStop() {
        super.onStop()
        // Release resources
    }

    override fun onDestroy() {
        super.onDestroy()
        // Final cleanup
    }
}

3. Service — Background Operations

A Service is a component that runs in the background to perform long-running operations without a user interface. Services are ideal for tasks like playing music, downloading files, or fetching data from a server.

Types of Services

TypeDescriptionUse Case
Started ServiceRuns until stopped or destroyedDownloading files, playing music
Bound ServiceAllows client-server interactionMusic player (play/pause control)
Intent ServiceHandles one-off tasks sequentiallyProcessing queue of requests
Foreground ServiceShows a notificationMusic playback, navigation

Basic Service Implementation

// MyService.kt
package com.example.myapp

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log

class MyService : Service() {

    companion object {
        private const val TAG = "MyService"
    }

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "Service created")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d(TAG, "Service started")

        // Do background work here
        Thread {
            // Simulate long-running task
            Thread.sleep(5000)
            Log.d(TAG, "Background task completed")
            stopSelf() // Stop the service when done
        }.start()

        return START_STICKY // Restart if killed by system
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "Service destroyed")
    }

    override fun onBind(intent: Intent?): IBinder? {
        // Return null for started services
        return null
    }
}

Starting and Stopping a Service

// In your Activity or Fragment
val intent = Intent(this, MyService::class.java)

// Start the service
startService(intent)

// Stop the service
stopService(intent)
Production Warning: Starting with Android 8.0 (API 26), apps cannot use startService() when they are in the background. Use Foreground Services with a notification or WorkManager for background tasks.

4. Broadcast Receiver — Responding to System Events

A Broadcast Receiver is a component that responds to system-wide broadcast announcements. It can listen to events like battery low, screen off, device boot, or custom broadcasts from your app.

Common System Broadcasts

ActionDescription
android.intent.action.BOOT_COMPLETEDDevice boot completed
android.intent.action.BATTERY_LOWBattery is low
android.intent.action.AIRPLANE_MODEAirplane mode toggled
android.net.conn.CONNECTIVITY_CHANGENetwork connectivity changed
android.intent.action.SCREEN_OFFScreen turned off

Broadcast Receiver Implementation

// BatteryBroadcastReceiver.kt
package com.example.myapp

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast

class BatteryBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        val action = intent.action
        if (Intent.ACTION_BATTERY_LOW == action) {
            Toast.makeText(context, "Battery is low!", Toast.LENGTH_LONG).show()
        }
    }
}

Registering a Broadcast Receiver

// Method 1: Register in AndroidManifest.xml (manifest-declared)
// <receiver android:name=".BatteryBroadcastReceiver">
//     <intent-filter>
//         <action android:name="android.intent.action.BATTERY_LOW" />
//     </intent-filter>
// </receiver>

// Method 2: Register dynamically (recommended for newer Android versions)
class MainActivity : AppCompatActivity() {

    private val batteryReceiver = BatteryBroadcastReceiver()

    override fun onResume() {
        super.onResume()
        val filter = IntentFilter(Intent.ACTION_BATTERY_LOW)
        registerReceiver(batteryReceiver, filter)
    }

    override fun onPause() {
        super.onPause()
        unregisterReceiver(batteryReceiver)
    }
}
Production Warning: Starting with Android 8.0 (API 26), most implicit broadcasts cannot be received in manifest-declared receivers. Use dynamic registration or JobScheduler for modern apps.

Sending Custom Broadcasts

// Send a custom broadcast
val intent = Intent("com.example.CUSTOM_EVENT")
intent.putExtra("message", "Hello from your app!")
sendBroadcast(intent)

// Receive custom broadcast
class CustomReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val message = intent.getStringExtra("message")
        Toast.makeText(context, "Received: $message", Toast.LENGTH_SHORT).show()
    }
}

5. Content Provider — Sharing Data

A Content Provider manages access to a structured set of data. It provides a standardized interface for sharing data between different applications. Content Providers are the only way to share data across apps securely.

Common Use Cases

  • Contacts Provider: Access device contacts
  • Media Store: Access photos, videos, and audio
  • Calendar Provider: Access calendar events
  • Files Provider: Share files with other apps

Using a Content Provider (Accessing Contacts)

// Access device contacts
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        readContacts()
    }

    private fun readContacts() {
        val projection = arrayOf(
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME
        )

        val cursor = contentResolver.query(
            ContactsContract.Contacts.CONTENT_URI,
            projection,
            null,
            null,
            null
        )

        cursor?.use {
            while (it.moveToNext()) {
                val name = it.getString(it.getColumnIndexOrThrow(
                    ContactsContract.Contacts.DISPLAY_NAME
                ))
                Log.d("Contacts", "Name: $name")
            }
        }
    }
}

Creating a Custom Content Provider

// MyContentProvider.kt
package com.example.myapp

import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri

class MyContentProvider : ContentProvider() {

    companion object {
        const val AUTHORITY = "com.example.myapp.provider"
        val CONTENT_URI = Uri.parse("content://$AUTHORITY/data")
    }

    override fun onCreate(): Boolean {
        // Initialize data source
        return true
    }

    override fun query(
        uri: Uri,
        projection: Array<String>?,
        selection: String?,
        selectionArgs: Array<String>?,
        sortOrder: String?
    ): Cursor? {
        // Return data based on URI
        // Called by other apps using ContentResolver
        return null
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        // Insert data
        return null
    }

    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<String>?
    ): Int {
        // Update data
        return 0
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
        // Delete data
        return 0
    }

    override fun getType(uri: Uri): String? {
        // Return MIME type
        return "vnd.android.cursor.dir/vnd.com.example.data"
    }
}

Declaring Content Provider in Manifest

<provider
    android:name=".MyContentProvider"
    android:authorities="com.example.myapp.provider"
    android:exported="true" />

6. Component Lifecycle Summary

ComponentLifecycle MethodsKey Points
ActivityonCreate, onStart, onResume, onPause, onStop, onDestroyHas UI, interacts with user
ServiceonCreate, onStartCommand, onBind, onDestroyNo UI, runs in background
Broadcast ReceiveronReceiveShort-lived, responds to events
Content ProvideronCreate, query, insert, update, deleteManages shared data

7. Production-Ready Checklist

  • ✅ Declare all components — Every component must be declared in AndroidManifest.xml.
  • ✅ Understand Activity lifecycle — Save and restore state in onSaveInstanceState().
  • ✅ Use Services wisely — Use WorkManager for background tasks on Android 8.0+.
  • ✅ Register receivers properly — Use dynamic registration for modern apps.
  • ✅ Handle permissions — Check and request permissions before accessing Content Providers.
  • ✅ Avoid memory leaks — Unregister receivers and unbind services in lifecycle callbacks.
  • ✅ Use foreground services — Show a notification for long-running services.
  • ✅ Test configuration changes — Handle screen rotation and other configuration changes.
Key Takeaway: Understanding the four components — Activities, Services, Broadcast Receivers, and Content Providers — is essential for building any Android app. Each component serves a specific purpose, and they work together to create a complete app experience. Mastering these components is the first step toward becoming a proficient Android developer.

Ready to master Android Development?

Build real-world Android apps with hands-on projects, mentor-led sessions, and placement support.

Explore Course