Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ If applicable, add screenshots to help explain your problem.
**Device (please complete the following information):**
- Device: [e.g. Pixel 6]
- OS: [e.g. Android 13]
- TriggerX Library Version [e.g. 1.0.0]
- TriggerX Library Version [e.g. 1.1.0]
- TriggerX Example App Version (if applicable) [e.g. 1.1]

**Additional context**
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- main

env:
VERSION_NAME: 1.0.0 # Update this value for each release
VERSION_NAME: 1.1.0 # Update this value for each release

jobs:
release:
Expand Down
40 changes: 23 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@
</a>
</p>


> **Note:** TriggerX is currently in Alpha. APIs may change.

TriggerX is a modular, developer-friendly **alarm execution** library for Android.

[See the full documentation](https://meticha.com/triggerx/docs)

It simplifies scheduling exact alarms and showing user-facing UIs at a specific time, even when
your app has been killed or without you managing foreground-service boilerplate, wake-locks, or
lock-screen flags.
Expand Down Expand Up @@ -66,7 +65,7 @@ the system details.

```toml
[versions]
triggerx = "0.0.4"
triggerx = "latest-version"

[dependencies]
triggerx = { module = "com.meticha:triggerx", version.ref = "triggerx" }
Expand All @@ -79,7 +78,7 @@ triggerx = { module = "com.meticha:triggerx", version.ref = "triggerx" }

```kotlin
dependencies {
implementation("com.meticha:triggerx:0.0.4")
implementation("com.meticha:triggerx:latest-version")
}
```

Expand All @@ -95,6 +94,8 @@ dependencies {

<!-- Permissions for scheduling exact alarms -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
```

### 1. Initialize in your Application class
Expand Down Expand Up @@ -150,7 +151,7 @@ fun HomeScreen(
) {
val context = LocalContext.current
val permissionState = rememberAppPermissionState()

val coroutines = rememberCoroutineScope()

Scaffold { paddingValues ->
Column(
Expand All @@ -163,10 +164,12 @@ fun HomeScreen(
) {
ElevatedButton(
onClick = {
if (permissionState.allRequiredGranted()) {
viewModel.scheduleOneMinuteAlarm(context)
} else {
permissionState.requestPermission()
coroutines.launch {
if (permissionState.allRequiredGranted()) {
viewModel.scheduleOneMinuteAlarm(context)
} else {
permissionState.requestPermission()
}
}
}
) {
Expand Down Expand Up @@ -268,6 +271,7 @@ fun HomeScreen(
) {
val context = LocalContext.current
val permissionState = rememberAppPermissionState()
val coroutines = rememberCoroutineScope()


Scaffold { paddingValues ->
Expand All @@ -281,12 +285,14 @@ fun HomeScreen(
) {
ElevatedButton(
onClick = {
if (permissionState.allRequiredGranted()) {
viewModel.scheduleOneMinuteAlarm(
context
)
} else {
permissionState.requestPermission()
coroutines.launch {
if (permissionState.allRequiredGranted()) {
viewModel.scheduleOneMinuteAlarm(
context
)
} else {
permissionState.requestPermission()
}
}
}
) {
Expand All @@ -301,7 +307,7 @@ Covered automatically:

| Permission | Version |
|--------------------------------|---------|
| ⏰ Exact alarm | API 31+ |
| ⏰ Exact alarm | API 31+ |
| 🔋 Ignore battery optimisation | all |
| 🖼 Overlay (only if needed) | all |
| 📢 Post-notification | API 33+ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class TriggerXApplication : Application() {
message = "Your alarm is ringing!",
channelName = "My Awesome App Notifications"
)
showAlarmActivityWhenAppIsActive = false
activityClass = AppAlarmActivity::class.java
alarmDataProvider = object : TriggerXDataProvider {
override suspend fun provideData(alarmId: Int, alarmType: String): Bundle {
Expand Down
6 changes: 4 additions & 2 deletions docs/docs/tutorial-basics/1-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Add this to your `build.gradle.kts`:

```kotlin
dependencies {
implementation("com.meticha:triggerx:0.0.5")
implementation("com.meticha:triggerx:1.1.0")
}
```

Expand All @@ -23,7 +23,7 @@ If you're using Version Catalogs:

```toml
[versions]
triggerx = "0.0.5"
triggerx = "1.1.0"

[libraries]
triggerx = { module = "com.meticha:triggerx", version.ref = "triggerx" }
Expand All @@ -44,4 +44,6 @@ dependencies {

<!-- Allows scheduling of exact alarms -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
```
11 changes: 7 additions & 4 deletions docs/docs/tutorial-basics/4-permission-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Here’s how to request permissions and schedule an alarm:
fun HomeScreen() {
val context = LocalContext.current
val permissionState = rememberAppPermissionState()
val coroutineScope = rememberCoroutineScope()

Scaffold { paddingValues ->
Column(
Expand All @@ -27,10 +28,12 @@ fun HomeScreen() {
) {
ElevatedButton(
onClick = {
if (permissionState.allRequiredGranted()) {
// do stuff
} else {
permissionState.requestPermission()
coroutineScope.launch{
if (permissionState.allRequiredGranted()) {
// do stuff
} else {
permissionState.requestPermission()
}
}
}
) {
Expand Down
53 changes: 28 additions & 25 deletions docs/docs/tutorial-basics/5-scheduling-alarm.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Here’s how to do it:
fun HomeScreen() {
val context = LocalContext.current
val permissionState = rememberAppPermissionState()
val coroutineScope = rememberCoroutineScope()

Scaffold { paddingValues ->
Column(
Expand All @@ -27,33 +28,35 @@ fun HomeScreen() {
) {
ElevatedButton(
onClick = {
if (permissionState.allRequiredGranted()) {
val triggerTime = Calendar.getInstance().apply {
add(Calendar.MINUTE, 1) // Triggers after 1 minute
}.timeInMillis

val scheduled = TriggerXAlarmScheduler().scheduleAlarm(
context = context,
triggerAtMillis = triggerTime,
type = "MEETING",
alarmId = 1
)

if (scheduled) {
Toast.makeText(
context,
"Alarm scheduled successfully. App can now be closed 🔔",
Toast.LENGTH_SHORT
).show()
coroutineScope.launch{
if (permissionState.allRequiredGranted()) {
val triggerTime = Calendar.getInstance().apply {
add(Calendar.MINUTE, 1) // Triggers after 1 minute
}.timeInMillis

val scheduled = TriggerXAlarmScheduler().scheduleAlarm(
context = context,
triggerAtMillis = triggerTime,
type = "MEETING",
alarmId = 1
)

if (scheduled) {
Toast.makeText(
context,
"Alarm scheduled successfully. App can now be closed 🔔",
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
context,
"Failed to schedule alarm. Please try again.",
Toast.LENGTH_SHORT
).show()
}
} else {
Toast.makeText(
context,
"Failed to schedule alarm. Please try again.",
Toast.LENGTH_SHORT
).show()
permissionState.requestPermission()
}
} else {
permissionState.requestPermission()
}
}
) {
Expand Down
Binary file not shown.
Binary file removed docs/docs/tutorial-extras/img/localeDropdown.png
Binary file not shown.
47 changes: 47 additions & 0 deletions docs/docs/tutorial-extras/showing-alarm-ui-conditionally.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: Showing Alarm UI conditionally
description: Configure TriggerX to show dynamic UI based on your Room database
sidebar_position: 2
---

# 💊 Showing Alarm UI conditionally

TriggerX gives you full control over **whether** to show the alarm screen based on your App’s logic, such
as values stored in a Room database, preferences, or feature flags.

You can configure these conditions using the `TriggerX.init()` function inside your `Application` class.

## 📱 1. Skip Alarm UI When App Is Active

If you don’t want the alarm UI to appear while the App is already in the foreground (e.g. user is using the app), set
the following:

```kotlin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()

TriggerX.init(this) {
showAlarmActivityWhenAppIsActive = false
}
}
}
```

This is useful when you want to handle the alarm inside the app manually without launching a separate screen.

## 💡 2. Skip Alarm UI When Device Is Active

If you want to avoid interrupting the user when they’re actively using the device (e.g. screen is on), set this:

```kotlin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()

TriggerX.init(this) {
shouldShowAlarmActivityWhenDeviceIsActive = false
}
}
}
```
36 changes: 18 additions & 18 deletions docs/docs/tutorial-extras/showing-dynamic-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,24 @@ fun HomeScreen() {

ElevatedButton(
onClick = {
if (permissionState.allRequiredGranted()) {
val db = AppDatabase.getInstance(context)
scope.launch {
db.taskDao().insert(Task(1, "Meeting", "Discuss the roadmap"))

val triggerTime = Calendar.getInstance().apply {
add(Calendar.MINUTE, 1)
}.timeInMillis

alarmScheduler.scheduleAlarm(
context = context,
triggerAtMillis = triggerTime,
type = "TASK",
alarmId = 1
)
}
} else {
permissionState.requestPermission()
scope.launch {
if (permissionState.allRequiredGranted()) {
val db = AppDatabase.getInstance(context)
db.taskDao().insert(Task(1, "Meeting", "Discuss the roadmap"))
val triggerTime = Calendar.getInstance().apply {
add(Calendar.MINUTE, 1)
}.timeInMillis
alarmScheduler.scheduleAlarm(
context = context,
triggerAtMillis = triggerTime,
type = "TASK",
alarmId = 1
)
} else {
permissionState.requestPermission()
}
}
}) {
Text("Schedule Dynamic Alarm")
Expand Down
2 changes: 1 addition & 1 deletion docs/src/components/HomepageFeatures/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const FeatureList: FeatureItem[] = [
),
},
{
title: 'Handles Permissions So You Don’t Have To',
title: 'Handles Permissions So That You Don’t Have To',
icon: '🔐',
description: (
<>
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("UnstableApiUsage")

pluginManagement {
repositories {
google {
Expand Down
4 changes: 2 additions & 2 deletions triggerx/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ mavenPublishing {
signAllPublications()


coordinates("com.meticha", "triggerx", "1.0.0")
coordinates("com.meticha", "triggerx", "1.1.0")

pom {
name = "triggerx"
description =
"A lightweight Android library for scheduling exact alarms with custom UIs. No foreground services or wake-lock hassle."
inceptionYear = "2025"
version = "1.0.0"
version = "1.1.0"
url = "https://github.com/meticha/triggerx.git"
licenses {
license {
Expand Down
Loading