Blog Infos
Author
Published
Topics
, , , ,
Published

 

Effective communication between different Android components or apps often requires careful management of inter-process communication (IPC). This guide provides a thorough exploration of Android’s IPC mechanisms, including Services, AIDL, Intents, Broadcasts, Messengers, and FileProviders.

1. Running a Service in a Separate Process

By default, all Android components (Activities, Services, etc.) run within a single app process. However, you can explicitly run a Service (or any other component) in its own separate Linux process by specifying the android:process attribute in your manifest:

<service
    android:name=".MyService"
    android:process=":remote"
    android:exported="true" />
  • android:process=":remote" creates a private process unique to your app.
  • android:process="com.example.remote" would create a global process that multiple apps signed with the same certificate can share.
Practical Implications:

When a Service is in a different process, all lifecycle methods (onCreate()onStartCommand()onBind()) run independently in that other process’s main thread. Importantly, this means:

  • If the caller (client) process is terminated or crashes, the Service’s separate process continues to run independently until explicitly stopped or terminated by the Android OS.
  • Communication with this Service becomes cross-process and must use Android’s IPC mechanisms. You cannot directly cast its IBinder to a local interface as you would within the same process because the objects exist in separate memory spaces.

The attribute android:exported="true" makes the Service available to other applications. If set to false, it’s accessible only from within your own application.

2. IPC with AIDL (Android Interface Definition Language)

AIDL is a structured IPC mechanism that defines a clear, type-safe interface for communication between processes. It allows passing primitive types, lists, and even custom Parcelable objects safely across processes.

Defining an AIDL Interface:

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

Implementing an 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
}

Binding from Client:

val intent = Intent().apply {
    component = ComponentName("com.example", "com.example.MyAidlService")
}

bindService(intent, object : ServiceConnection {
    override fun onServiceConnected(name: 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 on a Binder thread-pool. Always delegate heavy operations to background threads or coroutines to maintain responsiveness.

3. Simple IPC using Intents

The simplest way to exchange small data between Android apps or components is through Intents.

Explicit Intents (direct targeting):
val intent = Intent().apply {
    component = ComponentName("com.example.receiver", "com.example.receiver.TargetActivity")
    putExtra("key", "value")
}
startActivity(intent)
Implicit Intents (action-based):

Sender-side:

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

Receiver-side Manifest intent-filter:

<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>

Android matches the ACTION_SENDDEFAULT category, and MIME type to find suitable receiver components.

4. BroadcastReceivers for Fire-and-Forget Communication

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

Sender-side example:

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

Receiver-side (Manifest):

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

Receiver-side (Code):

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

Messenger is suitable for simple command-response scenarios using a Handler and Message queue. It’s simpler than AIDL but less flexible.

When to use Messenger:
  • For straightforward, one-way messages or simple request-response scenarios without complex data structures.

Service-side implementation:

class MessengerService : Service() {
    private val messenger = Messenger(Handler(Looper.getMainLooper()) { msg ->
        if (msg.what == 1) Log.i("MessengerService", "Received a message!")
        true
    })

    override fun onBind(intent: Intent): IBinder = messenger.binder
}

Client-side binding:

val connection = object : ServiceConnection {
    override fun onServiceConnected(name: ComponentName, service: IBinder) {
        val messenger = Messenger(service)
        messenger.send(Message.obtain(null, 1))
    }
    
    override fun onServiceDisconnected(name: ComponentName) {}
}

bindService(Intent(this, MessengerService::class.java), connection, BIND_AUTO_CREATE)
6. Sharing Files Securely with FileProvider

Due to Android’s sandbox restrictions, use FileProvider to securely share files via content:// URIs.

Why FileProvider?

  • Sandbox enforcement: Apps cannot access each other’s file systems directly.
  • API compatibility: Avoids FileUriExposedException from API 24 (Android 7.0 Nougat).
  • Secure permissions: Fine-grained, temporary file access without global permissions.

Provider declaration (Manifest):

<provider android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

Sharing file with Intent:

val file = File(context.getExternalFilesDir("Pictures"), "photo.jpg")
val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file)

val intent = Intent(Intent.ACTION_SEND).apply {
    type = "image/jpeg"
    putExtra(Intent.EXTRA_STREAM, uri)
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(intent, "Share image"))

Receiver-side example (Manifest and Activity handling shared files) included above.

7. ContentProvider

For structured data access across processes/apps:

Provider declaration (Manifest):

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

Provider implementation:

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

Client-side querying:

val uri = Uri.parse("content://com.example.myprovider/items")
val cursor = contentResolver.query(uri, null, null, null, null)
cursor?.use {
    while (it.moveToNext()) {
        // read data
    }
}

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Kobweb:Creating websites in Kotlin leveraging Compose HTML

Kobweb is a Kotlin web framework that aims to make web development enjoyable by building on top of Compose HTML and drawing inspiration from Jetpack Compose.
Watch Video

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kobweb

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author o ...

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kob ...

Jobs

Summary: Choosing the Right IPC Method

When deciding which IPC mechanism to use, think about the amount and structure of data you need to share as well as the complexity of your communication pattern:

  • Intents are your go-to for very simple data exchange or component navigation. If you just need to pass a few values (strings, numbers, small parcels) and launch an Activity or Service, Intents keep things lightweight and require no special setup.
  • Broadcasts shine when you want a “fire-and-forget” message delivered to multiple receivers. Use them for system-style notifications or whenever several parts of your app (or other apps) should react to the same event.
  • Messenger sits in the middle: it gives you a simple request-response channel via Handler/Message objects. It’s easy to implement and fine for basic command-and-control use cases, but it doesn’t scale well to complex APIs or large data structures.
  • AIDL is the heavyweight, type-safe solution. If you need a rich, multi‐method interface — passing lists, custom Parcelables, callbacks, etc. — AIDL gives you full control. Just be prepared to manage Binder threads, synchronization, and parcel overhead.
  • FileProvider handles file‐sharing securely. When you need to hand off large media or documents, FileProvider lets you expose content:// URIs without breaking Android’s sandbox or risking FileUriExposedException. It’s the recommended way to share files safely.
  • ContentProvider is built for structured data access (think database tables or cursor-based queries). If your app needs to let another app query, insert, update, or delete rows of data in a consistent way, ContentProvider provides the URI-based protocol and permission model to do it securely.

Choosing the right IPC method ensures efficient, secure, and maintainable communication across Android processes and apps.

This article was previously published on proandroiddev.com.

Menu