react-native-alarmageddon 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +169 -189
  3. package/android/build/.transforms/33d69af0aa8d226a34981fd71aab63e2/results.bin +1 -0
  4. package/android/build/.transforms/33d69af0aa8d226a34981fd71aab63e2/transformed/classes/classes_dex/classes.dex +0 -0
  5. package/android/build/generated/source/buildConfig/debug/com/rnalarmmodule/BuildConfig.java +10 -0
  6. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +41 -0
  7. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
  8. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
  9. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
  10. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  11. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  12. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +1 -0
  13. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_alarm_default.wav.flat +0 -0
  14. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +2 -0
  15. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  16. package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +2 -0
  17. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  18. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  19. package/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/react-native-alarmageddon_debug.kotlin_module +0 -0
  20. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/rnalarmmodule/BuildConfig.class +0 -0
  21. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +3 -0
  22. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +68 -0
  23. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +41 -0
  24. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
  25. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
  26. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/alarm_default.wav +0 -0
  27. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  28. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +2 -0
  29. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  30. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  31. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  32. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  33. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  34. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  35. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
  36. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  41. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  42. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
  43. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  44. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  45. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  46. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  47. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  48. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  49. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
  50. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  51. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
  52. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
  53. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
  54. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  55. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
  56. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
  57. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  58. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  59. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  60. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  61. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  62. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  63. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
  64. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  65. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  66. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  67. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  68. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  69. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  70. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
  71. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  72. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  73. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  74. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  75. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  76. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  77. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
  78. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  79. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  80. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  81. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  82. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  83. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  84. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
  85. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  86. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  87. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  88. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  89. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  90. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  91. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
  92. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
  93. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  94. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  95. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  96. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  97. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  98. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  99. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
  100. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  101. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  102. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  103. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  104. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  105. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  106. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  107. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  108. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  109. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  110. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  111. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  112. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  113. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
  114. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  115. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  116. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  117. package/android/build/outputs/logs/manifest-merger-debug-report.txt +71 -0
  118. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  119. package/android/build/tmp/kotlin-classes/debug/META-INF/react-native-alarmageddon_debug.kotlin_module +0 -0
  120. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/AlarmModule$Companion.class +0 -0
  121. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/AlarmModule.class +0 -0
  122. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/AlarmPackage.class +0 -0
  123. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/AlarmReceiver$Companion.class +0 -0
  124. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/AlarmReceiver.class +0 -0
  125. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/BootReceiver$Companion.class +0 -0
  126. package/android/build/tmp/kotlin-classes/debug/com/rnalarmmodule/BootReceiver.class +0 -0
  127. package/android/build.gradle +11 -21
  128. package/android/src/main/AndroidManifest.xml +16 -35
  129. package/android/src/main/java/com/rnalarmmodule/AlarmModule.kt +154 -390
  130. package/android/src/main/java/com/rnalarmmodule/AlarmPackage.kt +0 -1
  131. package/android/src/main/java/com/rnalarmmodule/AlarmReceiver.kt +290 -129
  132. package/android/src/main/java/com/rnalarmmodule/BootReceiver.kt +66 -124
  133. package/android/src/main/res/raw/alarm_default.wav +0 -0
  134. package/ios/{RNAlarmModule.m → AlarmModule.m} +9 -20
  135. package/ios/AlarmModule.swift +190 -36
  136. package/ios/RNAlarmModule-Bridging-Header.h +5 -1
  137. package/lib/index.d.ts +47 -85
  138. package/lib/index.d.ts.map +1 -1
  139. package/lib/index.js +60 -120
  140. package/lib/index.js.map +1 -1
  141. package/package.json +14 -23
  142. package/react-native-alarmageddon.podspec +10 -8
  143. package/react-native.config.js +3 -1
  144. package/src/index.ts +94 -201
  145. package/android/gradle.properties +0 -13
  146. package/android/src/main/java/com/rnalarmmodule/AlarmActivity.kt +0 -79
  147. package/android/src/main/java/com/rnalarmmodule/AlarmService.kt +0 -290
  148. package/android/src/main/res/raw/README.md +0 -36
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 react-native-alarmageddon
3
+ Copyright (c) 2025 Alameda Apps
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,34 +1,16 @@
1
1
  # react-native-alarmageddon
2
2
 
3
- 🔔 **Native exact alarm scheduling for React Native with sound, snooze, and boot persistence.**
4
-
5
- A powerful React Native library for scheduling alarms that:
6
- - Use Android's `AlarmManager.setAlarmClock()` for exact timing
7
- - Play alarm sounds at full volume
8
- - Show full-screen notifications that wake the device
9
- - Support snooze functionality
10
- - Persist across device reboots
11
- - Work even when the app is killed
3
+ Native exact alarm scheduling for React Native with sound, snooze, and boot persistence.
12
4
 
13
5
  ## Features
14
6
 
15
- - **Exact Alarms**: Uses `setAlarmClock()` for precise alarm timing
16
- - **Full-Screen Intent**: Wakes device and shows alarm UI
17
- - **Sound & Vibration**: Plays alarm sound at max volume with vibration
18
- - **Snooze Support**: Built-in snooze functionality
19
- - **Boot Persistence**: Alarms automatically reschedule after reboot
20
- - **Background Support**: Works when app is killed
21
- - **Auto-Stop**: Configurable auto-stop timer
22
- - ✅ **Event Emitter**: Listen for alarm state changes in JavaScript
23
-
24
- ## Platform Support
25
-
26
- | Platform | Status |
27
- |----------|--------|
28
- | Android | ✅ Full support |
29
- | iOS | ⚠️ Stub only (uses NOT_IMPLEMENTED errors) |
30
-
31
- > **Note**: iOS requires a different approach using `UNUserNotificationCenter`. Full iOS support is planned for a future release.
7
+ - **Exact Alarms**: Uses Android's `setExactAndAllowWhileIdle` for precise scheduling
8
+ - 🔊 **Alarm Sound**: Plays alarm audio at maximum volume with audio focus
9
+ - 💤 **Snooze Support**: Built-in snooze functionality with customizable duration
10
+ - 🔄 **Boot Persistence**: Alarms are automatically rescheduled after device reboot
11
+ - 📱 **Full-Screen Intent**: Shows notification with full-screen intent on lock screen
12
+ - 🎯 **Event Emitter**: Subscribe to alarm state changes in JavaScript
13
+ - 📲 **iOS Support**: Basic notification-based implementation for iOS
32
14
 
33
15
  ## Installation
34
16
 
@@ -44,22 +26,57 @@ The library uses autolinking, so no manual linking is required for React Native
44
26
 
45
27
  #### Permissions
46
28
 
47
- The required permissions are automatically merged into your `AndroidManifest.xml`:
29
+ The following permissions are automatically merged into your app's `AndroidManifest.xml`:
48
30
 
49
- ```xml
50
- <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
51
- <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
52
- <uses-permission android:name="android.permission.WAKE_LOCK" />
53
- <uses-permission android:name="android.permission.VIBRATE" />
54
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
55
- <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
56
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
57
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
31
+ - `SCHEDULE_EXACT_ALARM` - Required for exact alarm scheduling
32
+ - `USE_EXACT_ALARM` - Alternative permission for exact alarms
33
+ - `WAKE_LOCK` - Keep device awake during alarm
34
+ - `VIBRATE` - Vibration support
35
+ - `RECEIVE_BOOT_COMPLETED` - Reschedule alarms after reboot
36
+ - `POST_NOTIFICATIONS` - Required for Android 13+
37
+
38
+ #### Android 12+ (API 31+)
39
+
40
+ On Android 12 and above, you need to request the `SCHEDULE_EXACT_ALARM` permission. Users may need to grant this permission in Settings:
41
+
42
+ ```typescript
43
+ import RNAlarmModule from 'react-native-alarmageddon';
44
+
45
+ // Check and request permissions
46
+ const granted = await RNAlarmModule.ensurePermissions();
47
+ if (!granted) {
48
+ // Guide user to enable notification permissions
49
+ }
50
+ ```
51
+
52
+ #### Custom Alarm Sound
53
+
54
+ To use a custom alarm sound, place your audio file in:
55
+
56
+ ```
57
+ android/app/src/main/res/raw/alarm_default.wav
58
58
  ```
59
59
 
60
- #### Android 12+ (API 31+) Requirements
60
+ If no custom sound is found, the system default alarm sound will be used.
61
61
 
62
- Starting with Android 12, apps must request the `SCHEDULE_EXACT_ALARM` permission at runtime. This library handles this automatically, but you should call `ensurePermissions()` before scheduling alarms.
62
+ ### iOS Setup
63
+
64
+ Run pod install:
65
+
66
+ ```bash
67
+ cd ios && pod install
68
+ ```
69
+
70
+ Add the following to your `Info.plist` for notification permissions:
71
+
72
+ ```xml
73
+ <key>UIBackgroundModes</key>
74
+ <array>
75
+ <string>remote-notification</string>
76
+ </array>
77
+ ```
78
+
79
+ **Note**: iOS uses local notifications for alarms, which have limitations compared to Android (no persistent alarm sound, relies on system notification behavior).
63
80
 
64
81
  ## Usage
65
82
 
@@ -69,93 +86,65 @@ Starting with Android 12, apps must request the `SCHEDULE_EXACT_ALARM` permissio
69
86
  import RNAlarmModule from 'react-native-alarmageddon';
70
87
 
71
88
  // Request permissions first
72
- async function setupAlarms() {
73
- const granted = await RNAlarmModule.ensurePermissions();
74
- if (!granted) {
75
- console.warn('Alarm permissions not granted');
76
- return;
77
- }
78
-
79
- // Schedule an alarm for 5 minutes from now
80
- const triggerTime = new Date(Date.now() + 5 * 60 * 1000);
81
-
82
- await RNAlarmModule.scheduleAlarm({
83
- id: 'wake-up-alarm',
84
- datetimeISO: triggerTime.toISOString(),
85
- title: 'Wake Up!',
86
- body: 'Time to start your day',
87
- snoozeMinutes: 10,
88
- autoStopSeconds: 120,
89
- vibrate: true,
90
- });
91
- }
89
+ await RNAlarmModule.ensurePermissions();
90
+
91
+ // Schedule an alarm
92
+ await RNAlarmModule.scheduleAlarm({
93
+ id: 'medication-reminder-1',
94
+ datetimeISO: '2025-01-15T08:30:00',
95
+ title: 'Medication Reminder',
96
+ body: 'Time to take your morning medication',
97
+ });
98
+
99
+ // List all scheduled alarms
100
+ const alarms = await RNAlarmModule.listAlarms();
101
+ console.log('Scheduled alarms:', alarms);
102
+
103
+ // Cancel an alarm
104
+ await RNAlarmModule.cancelAlarm('medication-reminder-1');
92
105
  ```
93
106
 
94
- ### Listening for Alarm Events
107
+ ### Listening to Alarm Events
95
108
 
96
109
  ```typescript
97
- import { useEffect, useState } from 'react';
98
110
  import RNAlarmModule from 'react-native-alarmageddon';
111
+ import { useEffect } from 'react';
99
112
 
100
- function AlarmScreen() {
101
- const [activeAlarmId, setActiveAlarmId] = useState<string | null>(null);
102
-
113
+ function App() {
103
114
  useEffect(() => {
104
- // Check if an alarm is already playing when app opens
105
- RNAlarmModule.getCurrentAlarmPlaying().then((info) => {
106
- if (info) {
107
- setActiveAlarmId(info.activeAlarmId);
108
- }
109
- });
110
-
111
115
  // Subscribe to alarm state changes
112
- const unsubscribe = RNAlarmModule.onAlarmStateChange((alarmId) => {
113
- setActiveAlarmId(alarmId);
116
+ const subscription = RNAlarmModule.onAlarmStateChange((alarmId) => {
117
+ if (alarmId) {
118
+ console.log('Alarm started:', alarmId);
119
+ // Navigate to alarm screen, etc.
120
+ } else {
121
+ console.log('Alarm stopped');
122
+ }
114
123
  });
115
124
 
116
- return unsubscribe;
125
+ return () => subscription.remove();
117
126
  }, []);
118
127
 
119
- const handleStop = async () => {
120
- if (activeAlarmId) {
121
- await RNAlarmModule.stopCurrentAlarm(activeAlarmId);
122
- }
123
- };
124
-
125
- const handleSnooze = async () => {
126
- if (activeAlarmId) {
127
- await RNAlarmModule.snoozeCurrentAlarm(activeAlarmId, 10);
128
- }
129
- };
130
-
131
- if (!activeAlarmId) {
132
- return null;
133
- }
134
-
135
- return (
136
- <View>
137
- <Text>Alarm is ringing!</Text>
138
- <Button title="Stop" onPress={handleStop} />
139
- <Button title="Snooze 10 min" onPress={handleSnooze} />
140
- </View>
141
- );
128
+ // ... rest of your app
142
129
  }
143
130
  ```
144
131
 
145
- ### Managing Alarms
132
+ ### Stopping and Snoozing
146
133
 
147
134
  ```typescript
148
135
  import RNAlarmModule from 'react-native-alarmageddon';
149
136
 
150
- // List all scheduled alarms
151
- const alarms = await RNAlarmModule.listAlarms();
152
- console.log('Scheduled alarms:', alarms);
153
-
154
- // Cancel a specific alarm
155
- await RNAlarmModule.cancelAlarm('wake-up-alarm');
156
-
157
- // Snooze an alarm (reschedules it)
158
- await RNAlarmModule.snoozeAlarm('wake-up-alarm', 5);
137
+ // Get currently playing alarm
138
+ const activeAlarm = await RNAlarmModule.getCurrentAlarmPlaying();
139
+ if (activeAlarm) {
140
+ console.log('Active alarm:', activeAlarm.activeAlarmId);
141
+
142
+ // Stop the alarm
143
+ await RNAlarmModule.stopCurrentAlarm(activeAlarm.activeAlarmId);
144
+
145
+ // Or snooze for 5 minutes
146
+ await RNAlarmModule.snoozeCurrentAlarm(activeAlarm.activeAlarmId, 5);
147
+ }
159
148
  ```
160
149
 
161
150
  ## API Reference
@@ -164,129 +153,120 @@ await RNAlarmModule.snoozeAlarm('wake-up-alarm', 5);
164
153
 
165
154
  ```typescript
166
155
  type AlarmParams = {
167
- id: string; // Unique identifier
168
- datetimeISO: string; // ISO 8601 datetime string
169
- title?: string; // Notification title (default: "Alarm")
170
- body?: string; // Notification body (default: "")
171
- soundUri?: string; // Custom sound URI (uses system default if omitted)
172
- vibrate?: boolean; // Enable vibration (default: true)
173
- snoozeMinutes?: number; // Snooze duration (default: 5)
174
- autoStopSeconds?: number; // Auto-stop after N seconds (default: 60)
175
- };
176
-
177
- type StoredAlarm = {
178
- id: string;
179
- datetimeISO: string;
180
- title: string;
181
- body: string;
182
- vibrate: boolean;
183
- snoozeMinutes: number;
184
- autoStopSeconds: number;
156
+ id: string; // Unique identifier for the alarm
157
+ datetimeISO: string; // ISO 8601 timestamp (e.g., "2025-01-15T08:30:00")
158
+ title?: string; // Notification title (default: "Alarm")
159
+ body?: string; // Notification body (default: "")
185
160
  };
186
161
 
187
162
  type PermissionResult = {
188
163
  granted: boolean;
189
- exactAlarmGranted?: boolean;
190
164
  };
191
165
 
192
- type ActiveAlarmInfo = {
166
+ type ActiveAlarmState = {
193
167
  activeAlarmId: string;
194
168
  } | null;
169
+
170
+ type AlarmSubscription = {
171
+ remove: () => void;
172
+ };
195
173
  ```
196
174
 
197
175
  ### Methods
198
176
 
199
- #### Permissions
177
+ #### `ensurePermissions(): Promise<boolean>`
178
+
179
+ Requests notification permissions. On Android 13+, this will prompt for `POST_NOTIFICATIONS` permission.
180
+
181
+ Returns `true` if permissions are granted.
182
+
183
+ #### `scheduleAlarm(alarm: AlarmParams): Promise<void>`
184
+
185
+ Schedules an exact alarm. The alarm will persist through device reboots.
186
+
187
+ #### `cancelAlarm(id: string): Promise<void>`
188
+
189
+ Cancels a scheduled alarm by its ID.
190
+
191
+ #### `listAlarms(): Promise<AlarmParams[]>`
192
+
193
+ Returns an array of all currently scheduled alarms.
200
194
 
201
- | Method | Description |
202
- |--------|-------------|
203
- | `ensurePermissions()` | Request all required permissions. Returns `true` if granted. |
204
- | `requestNotificationPermission()` | Request notification permission (Android 13+). |
205
- | `requestExactAlarmPermission()` | Request exact alarm permission (Android 12+). Opens settings if needed. |
206
- | `checkExactAlarmPermission()` | Check if exact alarm permission is granted. |
207
- | `openExactAlarmSettings()` | Open system settings for exact alarm permission. |
195
+ #### `requestPermissions(): Promise<PermissionResult>`
208
196
 
209
- #### Alarm Management
197
+ Checks current permission status without prompting (Android).
210
198
 
211
- | Method | Description |
212
- |--------|-------------|
213
- | `scheduleAlarm(params)` | Schedule a new alarm. |
214
- | `cancelAlarm(id)` | Cancel a scheduled alarm. |
215
- | `listAlarms()` | Get all scheduled alarms. |
216
- | `snoozeAlarm(id, minutes)` | Reschedule an alarm for N minutes from now. |
199
+ #### `snoozeAlarm(id: string, minutes: number): Promise<void>`
217
200
 
218
- #### Active Alarm Control
201
+ Creates a new snooze alarm that will trigger after the specified minutes.
219
202
 
220
- | Method | Description |
221
- |--------|-------------|
222
- | `stopCurrentAlarm(id)` | Stop the currently playing alarm. |
223
- | `snoozeCurrentAlarm(id, minutes)` | Stop and snooze the current alarm. |
224
- | `getCurrentAlarmPlaying()` | Get info about the currently playing alarm. |
203
+ #### `stopCurrentAlarm(id: string): Promise<void>`
225
204
 
226
- #### Events
205
+ Stops the currently ringing alarm.
227
206
 
228
- | Method | Description |
229
- |--------|-------------|
230
- | `onAlarmStateChange(callback)` | Subscribe to alarm state changes. Returns unsubscribe function. |
231
- | `addEventListener(event, callback)` | Add event listener. Returns subscription for removal. |
207
+ #### `snoozeCurrentAlarm(id: string, minutes: number): Promise<void>`
232
208
 
233
- ## How It Works
209
+ Stops the current alarm and schedules it to ring again after the specified minutes.
234
210
 
235
- ### Android Architecture
211
+ #### `getCurrentAlarmPlaying(): Promise<ActiveAlarmState>`
236
212
 
237
- 1. **AlarmModule**: React Native bridge that schedules alarms via `AlarmManager`
238
- 2. **AlarmReceiver**: `BroadcastReceiver` that triggers when alarm fires
239
- 3. **AlarmService**: Foreground service that plays sound and shows notification
240
- 4. **AlarmActivity**: Transparent activity that wakes the screen
241
- 5. **BootReceiver**: Reschedules alarms after device reboot or time changes
213
+ Returns the ID of the currently ringing alarm, or `null` if no alarm is active.
242
214
 
243
- ### Alarm Scheduling
215
+ #### `onAlarmStateChange(callback: (alarmId: string | null) => void): AlarmSubscription`
244
216
 
245
- The library uses `AlarmManager.setAlarmClock()` which:
246
- - Is the most reliable way to schedule exact alarms on Android
247
- - Shows an alarm icon in the status bar
248
- - Can wake the device from Doze mode
249
- - Survives app kills
217
+ Subscribes to alarm state changes. The callback is invoked when an alarm starts (`alarmId` is the alarm ID) or stops (`alarmId` is `null`).
218
+
219
+ Returns a subscription object with a `remove()` method to unsubscribe.
220
+
221
+ ## Android Behavior Details
222
+
223
+ ### Alarm Triggering
224
+
225
+ - Alarms use `AlarmManager.setExactAndAllowWhileIdle()` for precise scheduling
226
+ - When triggered, the alarm plays at maximum volume on the `STREAM_ALARM` audio channel
227
+ - A wake lock is acquired to ensure the device stays awake during playback
228
+ - The alarm auto-stops after 60 seconds if not dismissed
229
+
230
+ ### Notification
231
+
232
+ - Shows a high-priority notification with full-screen intent
233
+ - Includes "Stop" and "Snooze" action buttons
234
+ - Tapping the notification opens the app with `alarm_id` in the intent extras
250
235
 
251
236
  ### Boot Persistence
252
237
 
253
- The `BootReceiver` listens for:
254
- - `BOOT_COMPLETED`: Device finished booting
255
- - `LOCKED_BOOT_COMPLETED`: Direct boot completed
256
- - `TIME_SET`: User changed system time
257
- - `TIMEZONE_CHANGED`: Timezone changed
258
- - `MY_PACKAGE_REPLACED`: App was updated
238
+ - The `BootReceiver` listens for `BOOT_COMPLETED`, `TIME_SET`, and `TIMEZONE_CHANGED`
239
+ - All scheduled alarms are rescheduled automatically
240
+ - Past alarms (that should have fired during device off time) are skipped
259
241
 
260
- When any of these events occur, all future alarms are rescheduled.
242
+ ## Limitations
261
243
 
262
- ## Troubleshooting
244
+ - **Expo**: This library is not compatible with Expo Go. You need to use a development build or eject.
245
+ - **iOS**: The iOS implementation uses local notifications, which don't provide the same persistent alarm experience as Android.
246
+ - **Background Restrictions**: Some device manufacturers (Samsung, Xiaomi, Huawei, etc.) may kill background processes. Users may need to disable battery optimization for your app.
263
247
 
264
- ### Alarm not firing
248
+ ## Troubleshooting
265
249
 
266
- 1. **Check permissions**: Ensure `SCHEDULE_EXACT_ALARM` is granted on Android 12+
267
- 2. **Battery optimization**: Exclude your app from battery optimization
268
- 3. **Verify time**: Ensure the scheduled time is in the future
250
+ ### Alarms not triggering on some devices
269
251
 
270
- ### Sound not playing
252
+ Some manufacturers implement aggressive battery optimization. Guide users to:
271
253
 
272
- 1. **Check volume**: Ensure alarm volume is not muted
273
- 2. **Custom sound**: Verify the sound URI is valid and accessible
254
+ 1. Disable battery optimization for your app
255
+ 2. Enable "Allow background activity"
256
+ 3. Add your app to any "protected apps" list
274
257
 
275
- ### Alarm not showing on lock screen
258
+ ### "Cannot schedule exact alarms" on Android 12+
276
259
 
277
- 1. **Notification permission**: Ensure `POST_NOTIFICATIONS` is granted on Android 13+
278
- 2. **Lock screen settings**: Check device notification settings for lock screen visibility
260
+ On Android 12+, exact alarm scheduling may require user permission. Check if `AlarmManager.canScheduleExactAlarms()` returns true, and if not, guide users to Settings > Apps > Special access > Alarms & reminders.
279
261
 
280
- ### After reboot, alarms are lost
262
+ ### Notifications not showing on Android 13+
281
263
 
282
- This shouldn't happen with the library, but verify:
283
- 1. The `BootReceiver` is properly declared in the manifest
284
- 2. Your app hasn't been force-stopped
264
+ Ensure you call `ensurePermissions()` before scheduling alarms. Android 13+ requires explicit `POST_NOTIFICATIONS` permission.
285
265
 
286
266
  ## Contributing
287
267
 
288
- Contributions are welcome! Please feel free to submit a Pull Request.
268
+ Contributions are welcome! Please read our contributing guidelines and submit pull requests to the main repository.
289
269
 
290
270
  ## License
291
271
 
292
- MIT License - see [LICENSE](LICENSE) for details.
272
+ MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Automatically generated file. DO NOT MODIFY
3
+ */
4
+ package com.rnalarmmodule;
5
+
6
+ public final class BuildConfig {
7
+ public static final boolean DEBUG = Boolean.parseBoolean("true");
8
+ public static final String LIBRARY_PACKAGE_NAME = "com.rnalarmmodule";
9
+ public static final String BUILD_TYPE = "debug";
10
+ }
@@ -0,0 +1,41 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.rnalarmmodule" >
4
+
5
+ <uses-sdk android:minSdkVersion="21" />
6
+
7
+ <!-- Alarm scheduling permissions -->
8
+ <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
9
+ <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
10
+
11
+ <!-- Wake device and play sound -->
12
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
13
+ <uses-permission android:name="android.permission.VIBRATE" />
14
+
15
+ <!-- Boot persistence -->
16
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
17
+
18
+ <!-- Notifications (Android 13+) -->
19
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
20
+
21
+ <application>
22
+
23
+ <!-- Alarm broadcast receiver -->
24
+ <receiver
25
+ android:name="com.rnalarmmodule.AlarmReceiver"
26
+ android:exported="false" />
27
+
28
+ <!-- Boot and time change receiver for rescheduling alarms -->
29
+ <receiver
30
+ android:name="com.rnalarmmodule.BootReceiver"
31
+ android:enabled="true"
32
+ android:exported="true" >
33
+ <intent-filter>
34
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
35
+ <action android:name="android.intent.action.TIME_SET" />
36
+ <action android:name="android.intent.action.TIMEZONE_CHANGED" />
37
+ </intent-filter>
38
+ </receiver>
39
+ </application>
40
+
41
+ </manifest>
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": 3,
3
+ "artifactType": {
4
+ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS",
5
+ "kind": "Directory"
6
+ },
7
+ "applicationId": "com.rnalarmmodule",
8
+ "variantName": "debug",
9
+ "elements": [
10
+ {
11
+ "type": "SINGLE",
12
+ "filters": [],
13
+ "attributes": [],
14
+ "outputFile": "AndroidManifest.xml"
15
+ }
16
+ ],
17
+ "elementType": "File"
18
+ }
@@ -0,0 +1,6 @@
1
+ aarFormatVersion=1.0
2
+ aarMetadataVersion=1.0
3
+ minCompileSdk=1
4
+ minCompileSdkExtension=0
5
+ minAndroidGradlePluginVersion=1.0.0
6
+ coreLibraryDesugaringEnabled=false
@@ -0,0 +1,2 @@
1
+ #Mon Jan 26 08:44:13 BRT 2026
2
+ com.rnalarmmodule.react-native-alarmageddon-main-6\:/raw/alarm_default.wav=/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/alarm_default.wav
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/main/res"><file name="alarm_default" path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/main/res/raw/alarm_default.wav" qualifiers="" type="raw"/></source></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug" generated-set="debug$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/build/generated/res/resValues/debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated" generated-set="generated$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/build/generated/res/resValues/debug"/></dataSet><mergedItems/></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/main/assets"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/debug/assets"/></dataSet><dataSet config="generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/build/intermediates/shader_assets/debug/compileDebugShaders/out"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/main/jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/debug/jniLibs"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/main/shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/quaresma/projects/my-meds-times/react-native-alarmageddon/android/src/debug/shaders"/></dataSet></merger>
@@ -0,0 +1,3 @@
1
+ R_DEF: Internal format may change without notice
2
+ local
3
+ raw alarm_default