Mobile Development 11 min read

Master Android IPC: Services, AIDL, Intents, Broadcasts, Messenger, FileProvider

This guide explores Android's inter‑process communication options—running services in separate processes, defining AIDL interfaces, using explicit and implicit Intents, BroadcastReceiver, Messenger, FileProvider, and ContentProvider—detailing configuration, code examples, and when to choose each method for efficient, secure component interaction.

AndroidPub
AndroidPub
AndroidPub
Master Android IPC: Services, AIDL, Intents, Broadcasts, Messenger, FileProvider

Effective communication between Android components or apps often requires careful management of inter‑process communication (IPC).

1. Running a Service in an Independent Process

By default all components run in the same process, but you can specify android:process in the manifest to run a Service (or other component) in a separate Linux process.

<service
    android:name=".MyService"
    android:process=":remote"
    android:exported="true"/>
android:process=":remote"

creates a private process for the app. android:process="com.example.remote" creates a global process that can be shared by multiple apps with the same signature.

Actual Impact

If the client process terminates or crashes, the Service in its own process continues to run until explicitly stopped by Android.

Communication becomes cross‑process and must use Android's IPC mechanisms; you cannot cast the IBinder to a local interface because the object resides in a different memory space.

The android:exported="true" attribute allows other apps to access the Service; setting it to false restricts access to the same app.

2. Using AIDL (Android Interface Definition Language)

AIDL provides a structured, type‑safe IPC mechanism for defining interfaces that can pass primitive types, lists, and custom Parcelable objects.

Define AIDL Interface

interface IMyService {
    int calculateSum(int a, int b);
}

Implement AIDL Service

class MyAidlService : Service() {
    private val binder = object : IMyService.Stub() {
        override fun calculateSum(a: Int, b: Int): Int = a + b
    }
    override fun onBind(intent: Intent): IBinder = binder
}

Client Binding

val intent = Intent().apply {
    component = ComponentName("com.example", "com.example.MyAidlService")
}
bindService(intent, object : ServiceConnection {
    override fun onServiceConnected(className: ComponentName, service: IBinder) {
        val myService = IMyService.Stub.asInterface(service)
        val result = myService.calculateSum(5, 10)
    }
    override fun onServiceDisconnected(name: ComponentName) {}
}, Context.BIND_AUTO_CREATE)

Note: AIDL methods run in the Binder thread pool; long‑running work should be moved to a background thread or coroutine to keep the service responsive.

3. Using Intent for Simple IPC

For small data exchanges, the simplest way is to use an Intent.

Explicit Intent (direct target)

val intent = Intent().apply {
    component = ComponentName("com.example.receiver", "com.example.receiver.TargetActivity")
    putExtra("key", "value")
}
startActivity(intent)

Implicit Intent (action‑based)

val intent = Intent(Intent.ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, "Hello from sender!")
}
startActivity(Intent.createChooser(intent, "Choose app"))

Receiver manifest declaration:

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

4. BroadcastReceiver for “Fire‑and‑Forget” Communication

Broadcasts are suitable for sending simple asynchronous messages to multiple receivers.

Sender

val intent = Intent("com.example.CUSTOM_ACTION").apply {
    putExtra("key", "value")
}
sendBroadcast(intent)

Receiver declaration in manifest

<receiver android:name=".MyReceiver" android:exported="true">
    <intent-filter>
        <action android:name="com.example.CUSTOM_ACTION"/>
    </intent-filter>
</receiver>

Receiver implementation

class MyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val data = intent.getStringExtra("key")
    }
}

5. Messenger for IPC

Messenger uses a Handler and a message queue for simple request‑response scenarios; it is easier than AIDL but less flexible.

Service side

class MessengerService : Service() {
    private val messenger = Messenger(Handler(Looper.getMainLooper()) { msg ->
        if (msg.what == 1) Log.d("MessengerService", "Received a message!")
        true
    })
    override fun onBind(intent: Intent): IBinder = messenger.binder
}

Client side

val connection = object : ServiceConnection {
    override fun onServiceConnected(className: ComponentName, service: IBinder) {
        val messenger = Messenger(service)
        val msg = Message.obtain(null, 1)
        messenger.send(msg)
    }
    override fun onServiceDisconnected(name: ComponentName) {}
}
bindService(Intent(this, MessengerService::class.java), connection, BIND_AUTO_CREATE)

6. FileProvider for Secure File Sharing

Because of Android’s sandbox, files must be shared via a content:// URI using FileProvider.

Sandbox limitation: apps cannot directly access each other’s file systems.

API compatibility: avoids FileUriExposedException on Android 7.0+.

Fine‑grained permission: shares files without requiring global storage permissions.

Declare Provider in manifest

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.example.contentprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

Share a file via Intent

val file = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "photo.jpg")
val uri = FileProvider.getUriForFile(context, "com.example.contentprovider", file)
val intent = Intent(Intent.ACTION_SEND).apply {
    type = "image/*"
    putExtra(Intent.EXTRA_STREAM, uri)
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(intent, "Share image"))

7. ContentProvider for Structured Data Access

ContentProvider enables cross‑process or cross‑app structured data queries, similar to a database table.

Declare Provider in manifest

<provider
    android:name=".MyProvider"
    android:authorities="com.example.myprovider"
    android:exported="true"
    android:grantUriPermissions="true"/>

Provider implementation

class MyProvider : ContentProvider() {
    override fun query(
        uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?
    ): Cursor? {
        // Return cursor data
        return null
    }
    // Implement insert(), update(), delete(), getType() as needed
}

Client query

val uri = Uri.parse("content://com.example.myprovider/items")
val cursor = contentResolver.query(uri, null, null, null, null)
cursor?.use {
    val data = it.getString(it.getColumnIndex("column_name"))
    // Process data
}

Conclusion: Choose the Right IPC Mechanism

When selecting an IPC mechanism, consider data volume, complexity, and communication pattern:

Intent: best for minimal data exchange or component navigation.

Broadcast: suitable for fire‑and‑forget notifications to multiple receivers.

Messenger: middle‑ground request‑response using Handler/Message; easy for simple cross‑process control.

AIDL: heavyweight, type‑safe solution for rich interfaces, lists, custom Parcelables, and concurrent access.

FileProvider: preferred for securely sharing large files or documents via content:// URIs.

ContentProvider: designed for structured data access across apps, offering a consistent permission model.

Choosing the appropriate IPC method ensures efficient, secure, and maintainable communication between Android processes and apps.

AndroidIPCServiceIntentBroadcastReceiverAIDLFileProviderMessenger
AndroidPub
Written by

AndroidPub

Senior Android Developer & Interviewer, regularly sharing original tech articles, learning resources, and practical interview guides. Welcome to follow and contribute!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.