This library provides a kind of IPC (inter-process communication) framework based on Android bound service with Messenger.
Following benefits are offered by the library to improve and simplify IPC development:
In this manner of IPC, Service works with Handler to deal with different types of Message objects.
Under the hood, each API is represented as a Message
object:
This could be mapped to the ApiHandler
interface abstraction exactly. Specifically, the API implementation needs to provide:
MessengerService
starts a dedicated HandlerThread to handle requests. ApiHandler
implementation uses Kotlin suspend
, which allows flexible threading model on top of the Kotlin coroutines.
The service provider should extend MessengerService
and provide API implementations. In AndroidManifest.xml
, declare <service>
with permission, intent filter, etc. if needed.
Meanwhile, the service client implements MessengerServiceClient
with API descriptors to make requests.
Here is an example:
import android.app.Application import android.content.Context import android.content.Intent import android.os.Bundle import kotlinx.coroutines.runBlocking class EchoService : MessengerService( listOf(EchoApiImpl), PermissionChecker { _, _, _ -> true }, ) class EchoServiceClient(context: Context) : MessengerServiceClient(context) { override val serviceIntentFactory: () -> Intent get() = { Intent("example.intent.action.ECHO") } fun echo(data: String?): String? = runBlocking { invoke(context.packageName, EchoApi, data).await() } } object EchoApi : ApiDescriptor<String?, String?> { private val codec = object : MessageCodec<String?> { override fun encode(data: String?) = Bundle(1).apply { putString("data", data) } override fun decode(data: Bundle): String? = data.getString("data", null) } override val id: Int get() = 1 override val requestCodec: MessageCodec<String?> get() = codec override val responseCodec: MessageCodec<String?> get() = codec } // This is not needed by EchoServiceClient. object EchoApiImpl : ApiHandler<String?, String?>, ApiDescriptor<String?, String?> by EchoApi { override suspend fun invoke( application: Application, myUid: Int, callingUid: Int, request: String?, ): String? = request override fun hasPermission( application: Application, myUid: Int, callingUid: Int, request: String?, ): Boolean = (request?.length ?: 0) <= 5 }