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 }