Skip to content

A Kotlin/Compose Multiplatform library to schedule alarms, display local notifications, and handle push notifications on Android and iOS.

License

Notifications You must be signed in to change notification settings

Tweener/alarmee

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Maven Central Version Kotlin Compose gradle-version License

Website X/Twitter


Alarmee logo Alarmee logo


Alarmee

Alarmee is a Kotlin/Compose Multiplatform library designed to simplify scheduling alarms and notifications on both Android and iOS platforms. With Alarmee, you can schedule one-time or repeating alarms, display platform-specific notifications, and now supports push notifications using Firebase Cloud Messaging (Android) and Apple Push Notification service (iOS).

Warning

Upgrading from v1.x?
Check out the Migration Guide to update your code for version 2.0.


Be sure to show your support by starring ⭐️ this repository, and feel free to contribute if you're interested!


🌟 Features

  • πŸ“… One-off alarm: Schedule an alarm to trigger at a specific date and time.
  • πŸ” Repeating alarm: Schedule recurring alarms with intervals: hourly, daily, weekly, monthly, yearly or custom (providing a duration).
  • ⚑️ Instant notifications: Send notifications immediately without scheduling them.
  • ☁️ Push notifications: Handle remote notifications via FCM/APNs.
  • 🎨 Extensible Configuration: Customize alarms and notifications with platform-specific settings.

πŸ› οΈ Installation

In your settings.gradle.kts file, add Maven Central to your repositories:

repositories {
  mavenCentral()
}

Then add Alarmee dependency to your module:

  • With version catalog, open libs.versions.toml:
[versions]
alarmee = "2.0.0" // Check latest version

[libraries]
alarmee = { group = "io.github.tweener", name = "alarmee", version.ref = "alarmee" }

Then in your module build.gradle.kts add:

dependencies {
  implementation(libs.alarmee)
}
  • Without version catalog, in your module build.gradle.kts add:
dependencies {
  val alarmee_version = "2.0.0" // Check latest version

  implementation("io.github.tweener:alarmee:$alarmee_version")
}

The latest version is: Maven Central Version


πŸ”§ Configuration

To get started with Alarmee, you need to provide a platform-specific configuration for Android and iOS. Follow these steps.

Warning

On iOS, make sure to add Firebase as a dependency (https://github.com/firebase/firebase-ios-sdk) to your Xcode project.

Then, in your target, add Background Modes (check Remote notifications) and Push notifications capabilities.

1. Declare an expect function in commonMain

In your commonMain source set, declare the following function to provide platform-specific configuration:

expect fun createAlarmeePlatformConfiguration(): AlarmeePlatformConfiguration

2. Provide the actual implementation in androidMain

In the androidMain source set, implement the actual function and return an AlarmeeAndroidPlatformConfiguration:

actual fun createAlarmeePlatformConfiguration(): AlarmeePlatformConfiguration =
  notificationIconResId = R.drawable.ic_notification,
  notificationIconColor = androidx.compose.ui.graphics.Color.Red, // Defaults to Color.Transparent is not specified
  notificationChannels = listOf(
    AlarmeeNotificationChannel(
      id = "dailyNewsChannelId",
      name = "Daily news notifications",
      importance = NotificationManager.IMPORTANCE_HIGH,
      soundFilename = "notifications_sound",
    ),
    AlarmeeNotificationChannel(
      id = "breakingNewsChannelId",
      name = "Breaking news notifications",
      importance = NotificationManager.IMPORTANCE_LOW,
    ),
    // List all the notification channels you need here
  )

3. Provide the actual implementation in iosMain

In the iosMain source set, implement the actual function and return an AlarmeeIosPlatformConfiguration:

val platformConfiguration: AlarmeePlatformConfiguration = AlarmeeIosPlatformConfiguration

4. Initialize AlarmeeService in your root Composable

In your shared root Composable (usually App() in commonMain), initialize the AlarmeeService with the platform configuration:

val alarmService: AlarmeeService = rememberAlarmeeService(
    platformConfiguration = createAlarmeePlatformConfiguration()
)

You can then use this instance to schedule or cancel alarms from your shared code.

πŸ§‘β€πŸ’» Usage

Important

Before using Alarmee, make sure the Notifications permission is granted on the target platform (Android official documentation, iOS official documentation).

Alternativally, you can use moko-permissions to easily handle permissions for you.

After initializing AlarmeeService, you can access the notification services:

Local Notifications (all platforms)

To send local notifications, use the local service:

val localService = alarmService.local
localService.schedule(...) // For instance

This is available on all targets (Android, iOS, desktop, web, etc.).

Push Notifications (mobile only)

To access push notifications (e.g. Firebase), cast the service to MobileAlarmeeService:

val pushService = (alarmService as? MobileAlarmeeService)?.push

This is only available on Android and iOS. On non-mobile targets, pushService will be null.

Local Notification Service

1. Scheduling a one-off alarm

You can schedule an alarm to be triggered at a specific time of the day, using AlarmeeService#schedule(...). When the alarm is triggered, a notification will be displayed.

For instance, to schedule an alarm on January 12th, 2025, at 5 PM:

localService.schedule(
    alarmee = Alarmee(
        uuid = "myAlarmId",
        notificationTitle = "πŸŽ‰ Congratulations! You've scheduled an Alarmee!",
        notificationBody = "This is the notification that will be displayed at the specified date and time.",
        scheduledDateTime = LocalDateTime(year = 2025, month = Month.JANUARY, dayOfMonth = 12, hour = 17, minute = 0),
    	deepLinkUri = "https://www.example.com", // A deep link URI to be retrieved in MainActivity#onNewIntent() on Android and in AppDelegate#userNotificationCenter() on iOS
        androidNotificationConfiguration = AndroidNotificationConfiguration( // Required configuration for Android target only (this parameter is ignored on iOS)
            priority = AndroidNotificationPriority.HIGH,
            channelId = "dailyNewsChannelId",
        ),
        iosNotificationConfiguration = IosNotificationConfiguration(),
    )
)

2. Scheduling a repeating alarm

You can specify a RepeatInterval parameter, which allows scheduling an alarm to repeat hourly, daily, weekly, monthly, yearly or custom, based on the specified scheduledDateTime.

Fixed repeat interval

You can use a fixed repeat interval to schedule an Alarmee every hour, day, week, month, or year. For instance, to schedule an alarm to repeat every day at 9:30 AM, you can use RepeatInterval.Daily:

localService.schedule(
    alarmee = Alarmee(
        uuid = "myAlarmId",
        notificationTitle = "πŸ” Congratulations! You've scheduled a daily repeating Alarmee!",
        notificationBody = "This notification will be displayed every day at 09:30.",
        scheduledDateTime = LocalDateTime(year = 2025, month = Month.JANUARY, dayOfMonth = 12, hour = 9, minute = 30),
        repeatInterval = RepeatInterval.Daily, // Will repeat every day
        androidNotificationConfiguration = AndroidNotificationConfiguration( // Required configuration for Android target only (this parameter is ignored on iOS)
            priority = AndroidNotificationPriority.DEFAULT,
            channelId = "dailyNewsChannelId",
        ),
        iosNotificationConfiguration = IosNotificationConfiguration(),
    )
)
Custom repeat interval

You can also set a custom repeat interval using RepeatInterval.Custom(duration) to schedule an Alarmee at a specified duration interval. For example, to schedule an alarm to repeat every 15 minutes, you can use RepeatInterval.Custom(duration = 15.minutes):

localService.schedule(
    alarmee = Alarmee(
        uuid = "myAlarmId",
        notificationTitle = "πŸ” Congratulations! You've scheduled a custom repeating Alarmee!",
        notificationBody = "This notification will be displayed every 15 minutes",
        repeatInterval = RepeatInterval.Custom(duration = 15.minutes), // Will repeat every 15 minutes
        androidNotificationConfiguration = AndroidNotificationConfiguration( // Required configuration for Android target only (this parameter is ignored on iOS)
            priority = AndroidNotificationPriority.DEFAULT,
            channelId = "otherChannelId",
        ),
        iosNotificationConfiguration = IosNotificationConfiguration(),
    )
)

3. Cancelling an alarm

An alarm can be cancelled using its uuid, using Alarmee#cancel(...). If an alarm with the specified uuid is found, it will be canceled, preventing any future notifications from being triggered for that alarm.

localService.cancel(uuid = "myAlarmId")

4. Trigger an alarm right away

You can trigger an alarm to instantly display a notification without scheduling it for a specific time:

localService.immediate(
    alarmee = Alarmee(
        uuid = "myAlarmId",
        notificationTitle = "πŸš€ Congratulations! You've pushed an Alarmee right now!",
        notificationBody = "This notification will be displayed right away",
        androidNotificationConfiguration = AndroidNotificationConfiguration( // Required configuration for Android target only (this parameter is ignored on iOS)
            priority = AndroidNotificationPriority.DEFAULT,
            channelId = "immediateChannelId",
        ),
        iosNotificationConfiguration = IosNotificationConfiguration(),
    )
)

5. Notification customization

Notification sound

You can customize the notification sound on both Android and iOS.

Warning

Custom sounds must be under 30 seconds in length on both Android and iOS. If the sound exceeds this limit, the system will fall back to the default notification sound..

πŸ€– Android

Notification sounds are set via AlarmeeNotificationChannel, which allows you to define the sound file for a specific notification channel.

  1. Place your custom sound file in the res/raw directory of your app (e.g., res/raw/notifications_sound.obb).
  2. Define a custom notification channel and provide the sound file name:
AlarmeeNotificationChannel(
    id = "dailyNewsChannelId",
    name = "Daily news notifications",
    importance = NotificationManager.IMPORTANCE_HIGH,
    soundFilename = "notifications_sound", // file name without the extension
)
🍎 iOS

Notification sounds are set in the IosNotificationConfiguration by providing the file name of the sound located in the app's bundle.

  1. Add your sound file to your Xcode project under the main bundle.
  2. Reference the sound file with its exact name and extension:
Alarmee(
    // ...
    iosNotificationConfiguration = IosNotificationConfiguration(
        soundFilename = "notifications_sound.wav",
    ),
)
Notification icon
πŸ€– Android
  • Global icon customization: You can set a default notification icon color and drawable for all notifications for your app.
AlarmeeAndroidPlatformConfiguration(
    notificationIconResId = R.drawable.ic_notification,
    notificationIconColor = Color.Yellow,
    // ...
)
  • Per-alarm icon customization: Override the global defaults by specifying the icon color and drawable for individual notifications.
localService.schedule(
    alarmee = Alarmee(
        androidNotificationConfiguration = AndroidNotificationConfiguration(
            notificationIconResId = R.drawable.ic_another_notification,
            notificationIconColor = Color.Red,
            // ...
        ),
        // ...
    )
)
🍎 iOS

On iOS, customizing icon colors and drawables is not supported.

Notification badge
πŸ€– Android

On Android, badge numbers are managed by the system and direct control over the badge number is not available in the notification API. The system automatically handles badge updates based on notifications.

🍎 iOS

You can customize the badge number displayed on the app icon for notifications. This is done using the IosNotificationConfiguration:

Alarmee(
    // ...
    iosNotificationConfiguration = IosNotificationConfiguration(
        badge = 4,
    ),
)

If badge = 0, the badge will be cleared from the app icon. If badge = null, the badge will not be updated.


Push Notification Service

The PushNotificationService handles push notifications for mobile platforms only (Android & iOS). It is available via the MobileAlarmeeService interface.

Currently, Alarmee automatically displays a notification when a push message is received, using the title and body fields from the payload. In a future release, developers will be able to handle the push payload manually and choose whether or not to display a notification.

πŸ”„ Migration Guide: From Alarmee 1.x to 2.0

Version 2.0 introduces a new API structure with a focus on clearer service boundaries and support for both local and push notifications. Follow these steps to migrate your existing code:


1. Replace AlarmeeScheduler with AlarmeeService

In 1.x, the entry point was:

val alarmeeScheduler: AlarmeeScheduler = rememberAlarmeeScheduler(
    platformConfiguration = platformConfiguration
)

In 2.0, it has been replaced by:

val alarmService: AlarmeeService = rememberAlarmeeService(
    platformConfiguration = platformConfiguration
)

2. Update function calls

All method calls on AlarmeeScheduler should now be redirected to the local notification service from AlarmeeService:

Replace:

alarmeeScheduler.schedule(alarmee)

With:

alarmService.local.schedule(alarmee)

Similarly, any other function calls (e.g., cancel(...), immediate(...), etc.) should follow this pattern:

// Before
alarmeeScheduler.cancel(alarmee)

// After
alarmService.local.cancel(alarmee)

3. Rename push(alarmee) to immediate(alarmee)

In 1.x, to instantly trigger a local notification, you called:

alarmeeScheduler.push(alarmee)

In 2.0, this method has been renamed to:

alarmService.local.immediate(alarmee)

βœ… Summary of Changes

1.x 2.0
AlarmeeScheduler AlarmeeService
rememberAlarmeeScheduler(...) rememberAlarmeeService(...)
alarmeeScheduler.schedule(...) alarmService.local.schedule(...)
alarmeeScheduler.cancel(...) alarmService.local.cancel(...)
alarmeeScheduler.push(...) alarmService.local.immediate(...)

πŸ‘¨β€πŸ’» Contributing

We love your input and welcome any contributions! Please read our contribution guidelines before submitting a pull request.


πŸ™ Credits


πŸ“œ Licence

Alarmee is licensed under the Apache-2.0.

About

A Kotlin/Compose Multiplatform library to schedule alarms, display local notifications, and handle push notifications on Android and iOS.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Contributors 3

  •  
  •  
  •