In this part, we’ll explore how to send Firebase Cloud Messaging (FCM) notifications using the Flareon library in a Kotlin Multiplatform environment.
The notification system in this project follows the Service pattern with a clean interface-implementation structure:
NotificationService: Interface defining the contractNotificationServiceImpl: Implementation using Flareon libraryThis design follows clean code principles by separating the interface from the implementation, making it easy to test and swap implementations if needed.
File: src/commonMain/kotlin/me/nathanfallet/ktornativeworkertutorial/services/NotificationService.kt
interface NotificationService {
suspend fun sendNotification(token: String, title: String, body: String)
}
This simple interface defines a single suspend function for sending notifications. It accepts:
token: The FCM device tokentitle: The notification titlebody: The notification body/messageFile: src/commonMain/kotlin/me/nathanfallet/ktornativeworkertutorial/services/NotificationServiceImpl.kt
class NotificationServiceImpl(
serviceAccountPath: String,
) : NotificationService {
private val serviceAccountJson = readFile(serviceAccountPath)
private val credentials = GoogleCredentials.fromJson(serviceAccountJson)
private val messaging = FcmService(credentials)
override suspend fun sendNotification(token: String, title: String, body: String) {
messaging.sendNotification(token, title, body)
}
}
serviceAccountPath parameterreadFile() function to load the JSON fileGoogleCredentials from the JSON contentFcmService instance using the credentialssendNotification() method delegates to the Flareon library’s FcmServicesuspend, enabling coroutine-based async operationsThe project uses the Flareon library (me.nathanfallet.flareon:messaging),
which provides:
In build.gradle.kts, Flareon is included in the common dependencies:
sourceSets {
commonMain.dependencies {
implementation(libs.flareon.messaging)
// ... other dependencies
}
}
And in gradle/libs.versions.toml:
[versions]
flareon = "0.1.1"
[libraries]
flareon-messaging = { module = "me.nathanfallet.flareon:messaging", version.ref = "flareon" }
To use FCM, you need a Firebase service account JSON file:
firebase-admin-sdk.json)The service account JSON contains:
Notice how the implementation uses readFile(), which is an expect function with platform-specific implementations:
java.io.File.readText()fopen, fread, fclose)This demonstrates how Kotlin Multiplatform allows you to write common business logic while using platform-specific APIs when necessary.
The current implementation is straightforward and doesn’t include explicit error handling. In a production environment, you might want to add:
However, this tutorial focuses on the clean, minimal implementation to demonstrate the core concepts.
The NotificationService is registered in the Koin dependency injection container (covered in Part 5), making it
available throughout the application:
single<NotificationService> {
NotificationServiceImpl(
serviceAccountPath = getEnv("SERVICE_ACCOUNT_PATH") ?: "firebase-admin-sdk.json",
)
}
This allows the service account path to be configured via environment variable, with a sensible default fallback.
The notification service demonstrates:
In the next part, we’ll explore how to set up AMQP message brokering with RabbitMQ to enable asynchronous notification processing.