react-native-alarmageddon 1.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.
@@ -0,0 +1,290 @@
1
+ package com.rnalarmmodule
2
+
3
+ import android.app.Notification
4
+ import android.app.NotificationChannel
5
+ import android.app.NotificationManager
6
+ import android.app.PendingIntent
7
+ import android.app.Service
8
+ import android.content.Context
9
+ import android.content.Intent
10
+ import android.media.AudioAttributes
11
+ import android.media.AudioManager
12
+ import android.media.MediaPlayer
13
+ import android.media.RingtoneManager
14
+ import android.net.Uri
15
+ import android.os.Build
16
+ import android.os.Handler
17
+ import android.os.IBinder
18
+ import android.os.Looper
19
+ import android.os.VibrationEffect
20
+ import android.os.Vibrator
21
+ import android.os.VibratorManager
22
+ import android.util.Log
23
+ import androidx.core.app.NotificationCompat
24
+
25
+ class AlarmService : Service() {
26
+
27
+ companion object {
28
+ private const val TAG = "AlarmService"
29
+ private const val NOTIFICATION_ID = 1001
30
+ private const val CHANNEL_ID = "alarm_channel"
31
+ private const val CHANNEL_NAME = "Alarm Notifications"
32
+
33
+ const val ACTION_START = "com.rnalarmmodule.ACTION_START"
34
+ const val ACTION_STOP = "com.rnalarmmodule.ACTION_STOP"
35
+ }
36
+
37
+ private var mediaPlayer: MediaPlayer? = null
38
+ private var vibrator: Vibrator? = null
39
+ private var autoStopHandler: Handler? = null
40
+ private var autoStopRunnable: Runnable? = null
41
+ private var currentAlarmId: String? = null
42
+
43
+ override fun onCreate() {
44
+ super.onCreate()
45
+ createNotificationChannel()
46
+ }
47
+
48
+ override fun onBind(intent: Intent?): IBinder? = null
49
+
50
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
51
+ when (intent?.action) {
52
+ ACTION_START -> {
53
+ val alarmId = intent.getStringExtra("alarmId") ?: "unknown"
54
+ val title = intent.getStringExtra("title") ?: "Alarm"
55
+ val body = intent.getStringExtra("body") ?: ""
56
+ val soundUri = intent.getStringExtra("soundUri") ?: ""
57
+ val vibrate = intent.getBooleanExtra("vibrate", true)
58
+ val snoozeMinutes = intent.getIntExtra("snoozeMinutes", 5)
59
+ val autoStopSeconds = intent.getIntExtra("autoStopSeconds", 60)
60
+
61
+ currentAlarmId = alarmId
62
+ startForeground(NOTIFICATION_ID, createNotification(alarmId, title, body, snoozeMinutes))
63
+ startAlarm(soundUri, vibrate, autoStopSeconds)
64
+ }
65
+ ACTION_STOP -> {
66
+ stopAlarm()
67
+ stopForeground(STOP_FOREGROUND_REMOVE)
68
+ stopSelf()
69
+ }
70
+ }
71
+ return START_NOT_STICKY
72
+ }
73
+
74
+ override fun onDestroy() {
75
+ stopAlarm()
76
+ super.onDestroy()
77
+ }
78
+
79
+ private fun createNotificationChannel() {
80
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
81
+ val channel = NotificationChannel(
82
+ CHANNEL_ID,
83
+ CHANNEL_NAME,
84
+ NotificationManager.IMPORTANCE_HIGH
85
+ ).apply {
86
+ description = "Alarm notifications"
87
+ setBypassDnd(true)
88
+ lockscreenVisibility = Notification.VISIBILITY_PUBLIC
89
+ setSound(null, null) // We handle sound separately
90
+ enableVibration(false) // We handle vibration separately
91
+ }
92
+
93
+ val notificationManager = getSystemService(NotificationManager::class.java)
94
+ notificationManager?.createNotificationChannel(channel)
95
+ }
96
+ }
97
+
98
+ private fun createNotification(alarmId: String, title: String, body: String, snoozeMinutes: Int): Notification {
99
+ // Stop action
100
+ val stopIntent = Intent(this, AlarmReceiver::class.java).apply {
101
+ action = AlarmReceiver.ACTION_STOP
102
+ putExtra("alarmId", alarmId)
103
+ }
104
+ val stopPendingIntent = PendingIntent.getBroadcast(
105
+ this,
106
+ alarmId.hashCode() + 1,
107
+ stopIntent,
108
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
109
+ )
110
+
111
+ // Snooze action
112
+ val snoozeIntent = Intent(this, AlarmReceiver::class.java).apply {
113
+ action = AlarmReceiver.ACTION_SNOOZE
114
+ putExtra("alarmId", alarmId)
115
+ putExtra("snoozeMinutes", snoozeMinutes)
116
+ }
117
+ val snoozePendingIntent = PendingIntent.getBroadcast(
118
+ this,
119
+ alarmId.hashCode() + 2,
120
+ snoozeIntent,
121
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
122
+ )
123
+
124
+ // Full screen intent to open app
125
+ val fullScreenIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
126
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
127
+ putExtra("alarmId", alarmId)
128
+ }
129
+ val fullScreenPendingIntent = fullScreenIntent?.let {
130
+ PendingIntent.getActivity(
131
+ this,
132
+ alarmId.hashCode() + 3,
133
+ it,
134
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
135
+ )
136
+ }
137
+
138
+ val builder = NotificationCompat.Builder(this, CHANNEL_ID)
139
+ .setContentTitle(title)
140
+ .setContentText(body)
141
+ .setSmallIcon(android.R.drawable.ic_lock_idle_alarm)
142
+ .setPriority(NotificationCompat.PRIORITY_MAX)
143
+ .setCategory(NotificationCompat.CATEGORY_ALARM)
144
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
145
+ .setOngoing(true)
146
+ .setAutoCancel(false)
147
+ .addAction(android.R.drawable.ic_menu_close_clear_cancel, "Stop", stopPendingIntent)
148
+ .addAction(android.R.drawable.ic_popup_sync, "Snooze ($snoozeMinutes min)", snoozePendingIntent)
149
+
150
+ if (fullScreenPendingIntent != null) {
151
+ builder.setFullScreenIntent(fullScreenPendingIntent, true)
152
+ builder.setContentIntent(fullScreenPendingIntent)
153
+ }
154
+
155
+ return builder.build()
156
+ }
157
+
158
+ private fun startAlarm(soundUri: String, vibrate: Boolean, autoStopSeconds: Int) {
159
+ Log.d(TAG, "Starting alarm: soundUri=$soundUri, vibrate=$vibrate, autoStop=${autoStopSeconds}s")
160
+
161
+ // Start sound
162
+ try {
163
+ mediaPlayer?.release()
164
+ mediaPlayer = MediaPlayer().apply {
165
+ setAudioAttributes(
166
+ AudioAttributes.Builder()
167
+ .setUsage(AudioAttributes.USAGE_ALARM)
168
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
169
+ .build()
170
+ )
171
+
172
+ val uri = if (soundUri.isNotEmpty()) {
173
+ try {
174
+ Uri.parse(soundUri)
175
+ } catch (e: Exception) {
176
+ getDefaultAlarmUri()
177
+ }
178
+ } else {
179
+ getDefaultAlarmUri()
180
+ }
181
+
182
+ try {
183
+ setDataSource(this@AlarmService, uri)
184
+ } catch (e: Exception) {
185
+ Log.w(TAG, "Failed to set data source, using default: ${e.message}")
186
+ setDataSource(this@AlarmService, getDefaultAlarmUri())
187
+ }
188
+
189
+ isLooping = true
190
+
191
+ // Set volume to max for alarm
192
+ val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
193
+ val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM)
194
+ audioManager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolume, 0)
195
+
196
+ prepare()
197
+ start()
198
+ }
199
+ } catch (e: Exception) {
200
+ Log.e(TAG, "Failed to start alarm sound: ${e.message}", e)
201
+ }
202
+
203
+ // Start vibration
204
+ if (vibrate) {
205
+ startVibration()
206
+ }
207
+
208
+ // Schedule auto-stop
209
+ if (autoStopSeconds > 0) {
210
+ autoStopHandler = Handler(Looper.getMainLooper())
211
+ autoStopRunnable = Runnable {
212
+ Log.d(TAG, "Auto-stopping alarm after ${autoStopSeconds}s")
213
+ stopAlarm()
214
+ stopForeground(STOP_FOREGROUND_REMOVE)
215
+ stopSelf()
216
+
217
+ // Clear active alarm state
218
+ val prefs = getSharedPreferences("rn_alarm_module_alarms", Context.MODE_PRIVATE)
219
+ prefs.edit().remove("active_alarm_id").apply()
220
+ AlarmModule.emitActiveAlarmId(null)
221
+ }
222
+ autoStopHandler?.postDelayed(autoStopRunnable!!, autoStopSeconds * 1000L)
223
+ }
224
+ }
225
+
226
+ private fun getDefaultAlarmUri(): Uri {
227
+ // Try to get default alarm sound
228
+ var uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
229
+ if (uri == null) {
230
+ uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
231
+ }
232
+ if (uri == null) {
233
+ uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
234
+ }
235
+ return uri ?: Uri.parse("android.resource://${packageName}/${R.raw.alarm_default}")
236
+ }
237
+
238
+ private fun startVibration() {
239
+ try {
240
+ vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
241
+ val vibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
242
+ vibratorManager.defaultVibrator
243
+ } else {
244
+ @Suppress("DEPRECATION")
245
+ getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
246
+ }
247
+
248
+ // Vibration pattern: wait 0ms, vibrate 500ms, wait 500ms, repeat
249
+ val pattern = longArrayOf(0, 500, 500, 500, 500, 500)
250
+
251
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
252
+ val effect = VibrationEffect.createWaveform(pattern, 0) // 0 = repeat from index 0
253
+ vibrator?.vibrate(effect)
254
+ } else {
255
+ @Suppress("DEPRECATION")
256
+ vibrator?.vibrate(pattern, 0)
257
+ }
258
+ } catch (e: Exception) {
259
+ Log.e(TAG, "Failed to start vibration: ${e.message}", e)
260
+ }
261
+ }
262
+
263
+ private fun stopAlarm() {
264
+ Log.d(TAG, "Stopping alarm")
265
+
266
+ // Stop sound
267
+ try {
268
+ mediaPlayer?.stop()
269
+ mediaPlayer?.release()
270
+ mediaPlayer = null
271
+ } catch (e: Exception) {
272
+ Log.e(TAG, "Error stopping media player: ${e.message}", e)
273
+ }
274
+
275
+ // Stop vibration
276
+ try {
277
+ vibrator?.cancel()
278
+ vibrator = null
279
+ } catch (e: Exception) {
280
+ Log.e(TAG, "Error stopping vibration: ${e.message}", e)
281
+ }
282
+
283
+ // Cancel auto-stop
284
+ autoStopRunnable?.let { autoStopHandler?.removeCallbacks(it) }
285
+ autoStopHandler = null
286
+ autoStopRunnable = null
287
+
288
+ currentAlarmId = null
289
+ }
290
+ }
@@ -0,0 +1,156 @@
1
+ package com.rnalarmmodule
2
+
3
+ import android.app.AlarmManager
4
+ import android.app.PendingIntent
5
+ import android.content.BroadcastReceiver
6
+ import android.content.Context
7
+ import android.content.Intent
8
+ import android.os.Build
9
+ import android.util.Log
10
+ import org.json.JSONArray
11
+
12
+ class BootReceiver : BroadcastReceiver() {
13
+
14
+ companion object {
15
+ private const val TAG = "BootReceiver"
16
+ private const val PREFS_NAME = "rn_alarm_module_alarms"
17
+ private const val ALARMS_KEY = "alarms"
18
+ }
19
+
20
+ override fun onReceive(context: Context, intent: Intent) {
21
+ val action = intent.action
22
+ Log.d(TAG, "onReceive: action=$action")
23
+
24
+ when (action) {
25
+ Intent.ACTION_BOOT_COMPLETED,
26
+ Intent.ACTION_LOCKED_BOOT_COMPLETED,
27
+ Intent.ACTION_TIME_CHANGED,
28
+ Intent.ACTION_TIMEZONE_CHANGED,
29
+ Intent.ACTION_MY_PACKAGE_REPLACED -> {
30
+ rescheduleAllAlarms(context)
31
+ }
32
+ else -> {
33
+ Log.w(TAG, "Unhandled action: $action")
34
+ }
35
+ }
36
+ }
37
+
38
+ private fun rescheduleAllAlarms(context: Context) {
39
+ Log.d(TAG, "Rescheduling all alarms...")
40
+
41
+ try {
42
+ val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
43
+ val alarmsJson = prefs.getString(ALARMS_KEY, "[]") ?: "[]"
44
+ val alarms = JSONArray(alarmsJson)
45
+
46
+ val currentTime = System.currentTimeMillis()
47
+ val validAlarms = JSONArray()
48
+ var rescheduledCount = 0
49
+
50
+ for (i in 0 until alarms.length()) {
51
+ val alarm = alarms.getJSONObject(i)
52
+ val id = alarm.getString("id")
53
+ val triggerTime = alarm.getLong("triggerTime")
54
+ val title = alarm.optString("title", "Alarm")
55
+ val body = alarm.optString("body", "")
56
+ val soundUri = alarm.optString("soundUri", "")
57
+ val vibrate = alarm.optBoolean("vibrate", true)
58
+ val snoozeMinutes = alarm.optInt("snoozeMinutes", 5)
59
+ val autoStopSeconds = alarm.optInt("autoStopSeconds", 60)
60
+
61
+ // Only reschedule alarms that are in the future
62
+ if (triggerTime > currentTime) {
63
+ scheduleAlarm(
64
+ context,
65
+ id,
66
+ triggerTime,
67
+ title,
68
+ body,
69
+ soundUri,
70
+ vibrate,
71
+ snoozeMinutes,
72
+ autoStopSeconds
73
+ )
74
+ validAlarms.put(alarm)
75
+ rescheduledCount++
76
+ Log.d(TAG, "Rescheduled alarm: id=$id, triggerTime=$triggerTime")
77
+ } else {
78
+ Log.d(TAG, "Skipping past alarm: id=$id, triggerTime=$triggerTime")
79
+ }
80
+ }
81
+
82
+ // Update stored alarms to only include valid (future) ones
83
+ prefs.edit().putString(ALARMS_KEY, validAlarms.toString()).apply()
84
+
85
+ Log.d(TAG, "Rescheduled $rescheduledCount alarms")
86
+ } catch (e: Exception) {
87
+ Log.e(TAG, "Failed to reschedule alarms: ${e.message}", e)
88
+ }
89
+ }
90
+
91
+ private fun scheduleAlarm(
92
+ context: Context,
93
+ id: String,
94
+ triggerTimeMillis: Long,
95
+ title: String,
96
+ body: String,
97
+ soundUri: String,
98
+ vibrate: Boolean,
99
+ snoozeMinutes: Int,
100
+ autoStopSeconds: Int
101
+ ) {
102
+ val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
103
+
104
+ val intent = Intent(context, AlarmReceiver::class.java).apply {
105
+ action = AlarmReceiver.ACTION_TRIGGER
106
+ putExtra("alarmId", id)
107
+ putExtra("title", title)
108
+ putExtra("body", body)
109
+ putExtra("soundUri", soundUri)
110
+ putExtra("vibrate", vibrate)
111
+ putExtra("snoozeMinutes", snoozeMinutes)
112
+ putExtra("autoStopSeconds", autoStopSeconds)
113
+ }
114
+
115
+ val pendingIntent = PendingIntent.getBroadcast(
116
+ context,
117
+ id.hashCode(),
118
+ intent,
119
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
120
+ )
121
+
122
+ try {
123
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
124
+ if (alarmManager.canScheduleExactAlarms()) {
125
+ alarmManager.setAlarmClock(
126
+ AlarmManager.AlarmClockInfo(triggerTimeMillis, pendingIntent),
127
+ pendingIntent
128
+ )
129
+ } else {
130
+ // Fallback to inexact alarm if exact permission not granted
131
+ alarmManager.setAndAllowWhileIdle(
132
+ AlarmManager.RTC_WAKEUP,
133
+ triggerTimeMillis,
134
+ pendingIntent
135
+ )
136
+ Log.w(TAG, "Exact alarm permission not granted, using inexact alarm for: $id")
137
+ }
138
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
139
+ alarmManager.setAlarmClock(
140
+ AlarmManager.AlarmClockInfo(triggerTimeMillis, pendingIntent),
141
+ pendingIntent
142
+ )
143
+ } else {
144
+ alarmManager.setExact(
145
+ AlarmManager.RTC_WAKEUP,
146
+ triggerTimeMillis,
147
+ pendingIntent
148
+ )
149
+ }
150
+ } catch (e: SecurityException) {
151
+ Log.e(TAG, "Security exception scheduling alarm $id: ${e.message}", e)
152
+ } catch (e: Exception) {
153
+ Log.e(TAG, "Failed to schedule alarm $id: ${e.message}", e)
154
+ }
155
+ }
156
+ }
@@ -0,0 +1,36 @@
1
+ # Alarm Sound Resources
2
+
3
+ This directory contains the default alarm sound for the react-native-alarmageddon library.
4
+
5
+ ## Default Alarm Sound
6
+
7
+ The library looks for `alarm_default.wav` (or `.mp3`, `.ogg`) in this directory as a fallback when:
8
+ 1. No custom sound URI is provided
9
+ 2. The system's default alarm sound cannot be loaded
10
+
11
+ ## Adding Your Own Default Sound
12
+
13
+ To include a default alarm sound with the library:
14
+
15
+ 1. Add your audio file to this directory with one of these names:
16
+ - `alarm_default.wav`
17
+ - `alarm_default.mp3`
18
+ - `alarm_default.ogg`
19
+
20
+ 2. The file should be:
21
+ - A short, loopable alarm sound (5-15 seconds recommended)
22
+ - Optimized for size
23
+ - Clear and alerting
24
+
25
+ ## Sound Priority
26
+
27
+ The library uses sounds in this order:
28
+ 1. Custom `soundUri` provided in `scheduleAlarm()` params
29
+ 2. Android system's default alarm sound (`RingtoneManager.TYPE_ALARM`)
30
+ 3. Android system's default notification sound
31
+ 4. Android system's default ringtone
32
+ 5. The `alarm_default` file from this directory (if exists)
33
+
34
+ ## Note
35
+
36
+ Since the system default alarm sound is usually available on all Android devices, you may not need to include a custom sound file. The library will gracefully fall back to system sounds.
@@ -0,0 +1,79 @@
1
+ import Foundation
2
+ import React
3
+
4
+ @objc(AlarmModule)
5
+ class AlarmModule: RCTEventEmitter {
6
+
7
+ private var hasListeners = false
8
+
9
+ override init() {
10
+ super.init()
11
+ }
12
+
13
+ @objc override static func requiresMainQueueSetup() -> Bool {
14
+ return false
15
+ }
16
+
17
+ override func supportedEvents() -> [String]! {
18
+ return ["activeAlarmId"]
19
+ }
20
+
21
+ override func startObserving() {
22
+ hasListeners = true
23
+ }
24
+
25
+ override func stopObserving() {
26
+ hasListeners = false
27
+ }
28
+
29
+ @objc func scheduleAlarm(_ alarm: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
30
+ // iOS stub - alarms are not yet implemented
31
+ // iOS uses different mechanisms (UNUserNotificationCenter) which require different handling
32
+ reject("NOT_IMPLEMENTED", "Alarm scheduling is not yet implemented for iOS. Consider using local notifications.", nil)
33
+ }
34
+
35
+ @objc func cancelAlarm(_ alarmId: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
36
+ // iOS stub
37
+ reject("NOT_IMPLEMENTED", "Alarm cancellation is not yet implemented for iOS.", nil)
38
+ }
39
+
40
+ @objc func listAlarms(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
41
+ // iOS stub - return empty array
42
+ resolve([])
43
+ }
44
+
45
+ @objc func requestPermissions(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
46
+ // iOS stub - would request notification permissions
47
+ resolve(["granted": true, "exactAlarmGranted": true])
48
+ }
49
+
50
+ @objc func checkExactAlarmPermission(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
51
+ // iOS doesn't have exact alarm permission concept
52
+ resolve(true)
53
+ }
54
+
55
+ @objc func openExactAlarmSettings(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
56
+ // iOS stub - no equivalent
57
+ resolve(nil)
58
+ }
59
+
60
+ @objc func snoozeAlarm(_ alarmId: String, minutes: NSNumber, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
61
+ // iOS stub
62
+ reject("NOT_IMPLEMENTED", "Alarm snooze is not yet implemented for iOS.", nil)
63
+ }
64
+
65
+ @objc func stopCurrentAlarm(_ alarmId: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
66
+ // iOS stub
67
+ resolve(nil)
68
+ }
69
+
70
+ @objc func snoozeCurrentAlarm(_ alarmId: String, minutes: NSNumber, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
71
+ // iOS stub
72
+ reject("NOT_IMPLEMENTED", "Alarm snooze is not yet implemented for iOS.", nil)
73
+ }
74
+
75
+ @objc func getCurrentAlarmPlaying(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
76
+ // iOS stub - no alarm playing
77
+ resolve(nil)
78
+ }
79
+ }
@@ -0,0 +1,3 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTEventEmitter.h>
3
+ #import <React/RCTUtils.h>
@@ -0,0 +1,48 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTEventEmitter.h>
3
+
4
+ @interface RCT_EXTERN_MODULE(AlarmModule, RCTEventEmitter)
5
+
6
+ RCT_EXTERN_METHOD(scheduleAlarm:(NSDictionary *)alarm
7
+ resolver:(RCTPromiseResolveBlock)resolve
8
+ rejecter:(RCTPromiseRejectBlock)reject)
9
+
10
+ RCT_EXTERN_METHOD(cancelAlarm:(NSString *)alarmId
11
+ resolver:(RCTPromiseResolveBlock)resolve
12
+ rejecter:(RCTPromiseRejectBlock)reject)
13
+
14
+ RCT_EXTERN_METHOD(listAlarms:(RCTPromiseResolveBlock)resolve
15
+ rejecter:(RCTPromiseRejectBlock)reject)
16
+
17
+ RCT_EXTERN_METHOD(requestPermissions:(RCTPromiseResolveBlock)resolve
18
+ rejecter:(RCTPromiseRejectBlock)reject)
19
+
20
+ RCT_EXTERN_METHOD(checkExactAlarmPermission:(RCTPromiseResolveBlock)resolve
21
+ rejecter:(RCTPromiseRejectBlock)reject)
22
+
23
+ RCT_EXTERN_METHOD(openExactAlarmSettings:(RCTPromiseResolveBlock)resolve
24
+ rejecter:(RCTPromiseRejectBlock)reject)
25
+
26
+ RCT_EXTERN_METHOD(snoozeAlarm:(NSString *)alarmId
27
+ minutes:(nonnull NSNumber *)minutes
28
+ resolver:(RCTPromiseResolveBlock)resolve
29
+ rejecter:(RCTPromiseRejectBlock)reject)
30
+
31
+ RCT_EXTERN_METHOD(stopCurrentAlarm:(NSString *)alarmId
32
+ resolver:(RCTPromiseResolveBlock)resolve
33
+ rejecter:(RCTPromiseRejectBlock)reject)
34
+
35
+ RCT_EXTERN_METHOD(snoozeCurrentAlarm:(NSString *)alarmId
36
+ minutes:(nonnull NSNumber *)minutes
37
+ resolver:(RCTPromiseResolveBlock)resolve
38
+ rejecter:(RCTPromiseRejectBlock)reject)
39
+
40
+ RCT_EXTERN_METHOD(getCurrentAlarmPlaying:(RCTPromiseResolveBlock)resolve
41
+ rejecter:(RCTPromiseRejectBlock)reject)
42
+
43
+ + (BOOL)requiresMainQueueSetup
44
+ {
45
+ return NO;
46
+ }
47
+
48
+ @end