react-native-alarms 0.0.0-stage → 0.0.2
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.
- package/.bundle/config +2 -0
- package/AlarmService.d.ts +112 -0
- package/AlarmService.ts +196 -0
- package/README.md +385 -2
- package/android/app/build.gradle +119 -0
- package/android/app/debug.keystore +0 -0
- package/android/app/proguard-rules.pro +10 -0
- package/android/app/src/main/AndroidManifest.xml +81 -0
- package/android/app/src/main/java/com/reactnativealarm/MainActivity.kt +29 -0
- package/android/app/src/main/java/com/reactnativealarm/MainApplication.kt +29 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmData.kt +134 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmModule.kt +263 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmPackage.kt +24 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmReceiver.kt +43 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmRingActivity.kt +86 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmScheduler.kt +74 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmService.kt +285 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/AlarmStore.kt +13 -0
- package/android/app/src/main/java/com/reactnativealarm/alarm/BootReceiver.kt +29 -0
- package/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/values/strings.xml +3 -0
- package/android/app/src/main/res/values/styles.xml +9 -0
- package/android/build.gradle +21 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/android/gradle.properties +49 -0
- package/android/gradlew +248 -0
- package/android/gradlew.bat +98 -0
- package/android/settings.gradle +6 -0
- package/app.json +4 -0
- package/index.d.ts +20 -0
- package/index.js +12 -0
- package/index.ts +21 -0
- package/ios/.xcode.env +11 -0
- package/ios/Podfile +34 -0
- package/ios/Podfile.lock +2179 -0
- package/ios/ReactNativeAlarm/AppDelegate.swift +14 -0
- package/ios/ReactNativeAlarm/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/ios/ReactNativeAlarm/Images.xcassets/Contents.json +6 -0
- package/ios/ReactNativeAlarm/Info.plist +79 -0
- package/ios/ReactNativeAlarm/LaunchScreen.storyboard +47 -0
- package/ios/ReactNativeAlarm/PrivacyInfo.xcprivacy +37 -0
- package/ios/ReactNativeAlarm/SceneDelegate.swift +56 -0
- package/ios/ReactNativeAlarm.xcodeproj/project.pbxproj +530 -0
- package/ios/ReactNativeAlarm.xcodeproj/xcshareddata/xcschemes/ReactNativeAlarm.xcscheme +88 -0
- package/ios/ReactNativeAlarm.xcworkspace/contents.xcworkspacedata +10 -0
- package/ios/alarm/AlarmData.swift +97 -0
- package/ios/alarm/AlarmKitBackend.swift +212 -0
- package/ios/alarm/AlarmModule.m +53 -0
- package/ios/alarm/AlarmModule.swift +284 -0
- package/ios/alarm/AlarmStore.swift +51 -0
- package/ios/alarm/NotificationBackend.swift +227 -0
- package/package.json +91 -3
- package/specs/NativeAlarm.ts +95 -0
package/.bundle/config
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlarmService - High-level alarm management API
|
|
3
|
+
* Provides convenient wrapper methods for the native alarm module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
AlarmConfig,
|
|
8
|
+
Alarm,
|
|
9
|
+
AlarmPermission,
|
|
10
|
+
AlarmEvent,
|
|
11
|
+
} from './specs/NativeAlarm';
|
|
12
|
+
|
|
13
|
+
type AlarmEventListener = (alarm: AlarmEvent) => void;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* High-level alarm service for managing alarms
|
|
17
|
+
*/
|
|
18
|
+
export class AlarmService {
|
|
19
|
+
/**
|
|
20
|
+
* Initialize the alarm service and set up event listeners
|
|
21
|
+
*/
|
|
22
|
+
static initialize(): void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Cleanup event listeners
|
|
26
|
+
*/
|
|
27
|
+
static cleanup(): void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Register a listener for when alarms fire
|
|
31
|
+
* @returns unsubscribe function
|
|
32
|
+
*/
|
|
33
|
+
static onAlarmFired(listener: AlarmEventListener): () => void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Register a listener for when alarms are dismissed
|
|
37
|
+
* @returns unsubscribe function
|
|
38
|
+
*/
|
|
39
|
+
static onAlarmDismissed(listener: AlarmEventListener): () => void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Register a listener for when alarms are snoozed
|
|
43
|
+
* @returns unsubscribe function
|
|
44
|
+
*/
|
|
45
|
+
static onAlarmSnoozed(listener: AlarmEventListener): () => void;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check the current alarm permissions
|
|
49
|
+
*/
|
|
50
|
+
static checkPermission(): Promise<AlarmPermission>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Request alarm permissions
|
|
54
|
+
*/
|
|
55
|
+
static requestPermission(): Promise<AlarmPermission>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Schedule a new alarm
|
|
59
|
+
* @returns alarm ID
|
|
60
|
+
*/
|
|
61
|
+
static scheduleAlarm(config: AlarmConfig): Promise<string>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Update an existing alarm
|
|
65
|
+
* @returns boolean indicating success
|
|
66
|
+
*/
|
|
67
|
+
static updateAlarm(alarmId: string, config: AlarmConfig): Promise<boolean>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Cancel an alarm
|
|
71
|
+
* @returns boolean if alarm existed
|
|
72
|
+
*/
|
|
73
|
+
static cancelAlarm(alarmId: string): Promise<boolean>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Cancel all alarms
|
|
77
|
+
*/
|
|
78
|
+
static cancelAllAlarms(): Promise<void>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Stop the currently ringing alarm
|
|
82
|
+
*/
|
|
83
|
+
static stopAlarm(alarmId: string): Promise<void>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Snooze the currently ringing alarm
|
|
87
|
+
* @param minutes - snooze duration (defaults to alarm's snoozeMinutes)
|
|
88
|
+
*/
|
|
89
|
+
static snoozeAlarm(alarmId: string, minutes?: number): Promise<void>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the currently ringing alarm (if any)
|
|
93
|
+
*/
|
|
94
|
+
static getRingingAlarm(): Promise<Alarm | null>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get a specific alarm by ID
|
|
98
|
+
*/
|
|
99
|
+
static getAlarm(alarmId: string): Promise<Alarm | null>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get all scheduled alarms
|
|
103
|
+
*/
|
|
104
|
+
static getAllAlarms(): Promise<Alarm[]>;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if an alarm is scheduled
|
|
108
|
+
*/
|
|
109
|
+
static isScheduled(alarmId: string): Promise<boolean>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export default AlarmService;
|
package/AlarmService.ts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlarmService - High-level alarm management API
|
|
3
|
+
*
|
|
4
|
+
* This module provides a convenient wrapper around the native alarm module
|
|
5
|
+
* with additional features like event listeners and state management.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
9
|
+
import type {
|
|
10
|
+
AlarmConfig,
|
|
11
|
+
Alarm,
|
|
12
|
+
AlarmPermission,
|
|
13
|
+
AlarmEvent,
|
|
14
|
+
} from './specs/NativeAlarm';
|
|
15
|
+
|
|
16
|
+
const { Alarm: NativeAlarm } = NativeModules;
|
|
17
|
+
|
|
18
|
+
// Guard against module not being linked
|
|
19
|
+
const alarm = NativeAlarm ? require('./specs/NativeAlarm').default : null;
|
|
20
|
+
|
|
21
|
+
const alarmEmitter = NativeAlarm ? new NativeEventEmitter(NativeAlarm) : null;
|
|
22
|
+
|
|
23
|
+
type AlarmEventListener = (alarm: AlarmEvent) => void;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* High-level alarm service for managing alarms
|
|
27
|
+
*/
|
|
28
|
+
export class AlarmService {
|
|
29
|
+
private static listeners: {
|
|
30
|
+
fired: Set<AlarmEventListener>;
|
|
31
|
+
dismissed: Set<AlarmEventListener>;
|
|
32
|
+
snoozed: Set<AlarmEventListener>;
|
|
33
|
+
} = {
|
|
34
|
+
fired: new Set(),
|
|
35
|
+
dismissed: new Set(),
|
|
36
|
+
snoozed: new Set(),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
private static subscriptions: any[] = [];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initialize the alarm service and set up event listeners
|
|
43
|
+
*/
|
|
44
|
+
static initialize() {
|
|
45
|
+
if (!alarmEmitter || !this.subscriptions.length) {
|
|
46
|
+
this.subscriptions = [
|
|
47
|
+
alarmEmitter?.addListener('onAlarmFired', (data: any) => {
|
|
48
|
+
this.listeners.fired.forEach(listener => listener(data as AlarmEvent));
|
|
49
|
+
}),
|
|
50
|
+
alarmEmitter?.addListener('onAlarmDismissed', (data: any) => {
|
|
51
|
+
this.listeners.dismissed.forEach(listener => listener(data as AlarmEvent));
|
|
52
|
+
}),
|
|
53
|
+
alarmEmitter?.addListener('onAlarmSnoozed', (data: any) => {
|
|
54
|
+
this.listeners.snoozed.forEach(listener => listener(data as AlarmEvent));
|
|
55
|
+
}),
|
|
56
|
+
].filter(Boolean);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Cleanup event listeners
|
|
62
|
+
*/
|
|
63
|
+
static cleanup() {
|
|
64
|
+
this.subscriptions.forEach(sub => sub?.remove());
|
|
65
|
+
this.subscriptions = [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Register a listener for when alarms fire
|
|
70
|
+
*/
|
|
71
|
+
static onAlarmFired(listener: AlarmEventListener) {
|
|
72
|
+
this.initialize();
|
|
73
|
+
this.listeners.fired.add(listener);
|
|
74
|
+
return () => this.listeners.fired.delete(listener);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Register a listener for when alarms are dismissed
|
|
79
|
+
*/
|
|
80
|
+
static onAlarmDismissed(listener: AlarmEventListener) {
|
|
81
|
+
this.initialize();
|
|
82
|
+
this.listeners.dismissed.add(listener);
|
|
83
|
+
return () => this.listeners.dismissed.delete(listener);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Register a listener for when alarms are snoozed
|
|
88
|
+
*/
|
|
89
|
+
static onAlarmSnoozed(listener: AlarmEventListener) {
|
|
90
|
+
this.initialize();
|
|
91
|
+
this.listeners.snoozed.add(listener);
|
|
92
|
+
return () => this.listeners.snoozed.delete(listener);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Check the current alarm permissions
|
|
97
|
+
*/
|
|
98
|
+
static async checkPermission(): Promise<AlarmPermission> {
|
|
99
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
100
|
+
return alarm.checkPermission();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Request alarm permissions
|
|
105
|
+
*/
|
|
106
|
+
static async requestPermission(): Promise<AlarmPermission> {
|
|
107
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
108
|
+
return alarm.requestPermission();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Schedule a new alarm
|
|
113
|
+
*/
|
|
114
|
+
static async scheduleAlarm(config: AlarmConfig): Promise<string> {
|
|
115
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
116
|
+
return alarm.scheduleAlarm(config);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Update an existing alarm
|
|
121
|
+
*/
|
|
122
|
+
static async updateAlarm(
|
|
123
|
+
alarmId: string,
|
|
124
|
+
config: AlarmConfig,
|
|
125
|
+
): Promise<boolean> {
|
|
126
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
127
|
+
return alarm.updateAlarm(alarmId, config);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Cancel an alarm
|
|
132
|
+
*/
|
|
133
|
+
static async cancelAlarm(alarmId: string): Promise<boolean> {
|
|
134
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
135
|
+
return alarm.cancelAlarm(alarmId);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Cancel all alarms
|
|
140
|
+
*/
|
|
141
|
+
static async cancelAllAlarms(): Promise<void> {
|
|
142
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
143
|
+
return alarm.cancelAllAlarms();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Stop the currently ringing alarm
|
|
148
|
+
*/
|
|
149
|
+
static async stopAlarm(alarmId: string): Promise<void> {
|
|
150
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
151
|
+
return alarm.stopAlarm(alarmId);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Snooze the currently ringing alarm
|
|
156
|
+
*/
|
|
157
|
+
static async snoozeAlarm(alarmId: string, minutes?: number): Promise<void> {
|
|
158
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
159
|
+
return alarm.snoozeAlarm(alarmId, minutes ?? 5);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get the currently ringing alarm (if any)
|
|
164
|
+
*/
|
|
165
|
+
static async getRingingAlarm(): Promise<Alarm | null> {
|
|
166
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
167
|
+
return alarm.getRingingAlarm();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get a specific alarm by ID
|
|
172
|
+
*/
|
|
173
|
+
static async getAlarm(alarmId: string): Promise<Alarm | null> {
|
|
174
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
175
|
+
return alarm.getAlarm(alarmId);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get all scheduled alarms
|
|
180
|
+
*/
|
|
181
|
+
static async getAllAlarms(): Promise<Alarm[]> {
|
|
182
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
183
|
+
return alarm.getAllAlarms();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Check if an alarm is scheduled
|
|
188
|
+
*/
|
|
189
|
+
static async isScheduled(alarmId: string): Promise<boolean> {
|
|
190
|
+
if (!alarm) throw new Error('Alarm module not linked');
|
|
191
|
+
return alarm.isScheduled(alarmId);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Export a singleton instance
|
|
196
|
+
export default AlarmService;
|
package/README.md
CHANGED
|
@@ -1,3 +1,386 @@
|
|
|
1
|
-
#
|
|
1
|
+
# React Native Alarms 🔔
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A powerful, cross-platform alarm management library for React Native. Schedule, manage, and control alarms on both Android and iOS with a unified API.
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/js/react-native-alarms)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
✨ **Cross-Platform Support**
|
|
11
|
+
- Seamless support for both Android and iOS
|
|
12
|
+
- Native alarm implementation for reliable delivery
|
|
13
|
+
- Background execution support
|
|
14
|
+
|
|
15
|
+
🎯 **Comprehensive Alarm Management**
|
|
16
|
+
- Schedule one-time and recurring alarms (daily, weekly, interval-based)
|
|
17
|
+
- Update and cancel alarms
|
|
18
|
+
- Snooze and stop currently ringing alarms
|
|
19
|
+
- Query alarm status
|
|
20
|
+
|
|
21
|
+
🔔 **Event-Driven Architecture**
|
|
22
|
+
- Real-time events for alarm firing, dismissal, and snoozing
|
|
23
|
+
- Easy event listener registration and cleanup
|
|
24
|
+
- Full-screen alarm display on iOS 26+ with AlarmKit
|
|
25
|
+
- Fallback to notifications on older devices
|
|
26
|
+
|
|
27
|
+
🔐 **Permission Handling**
|
|
28
|
+
- Automatic permission checking and requesting
|
|
29
|
+
- Platform-specific permission management
|
|
30
|
+
- Detailed permission status reporting
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install react-native-alarms
|
|
36
|
+
# or
|
|
37
|
+
yarn add react-native-alarms
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Native Module Linking
|
|
41
|
+
|
|
42
|
+
Since this is a native module, you'll need to link it:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd ios && pod install && cd ..
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For Android, the native code should auto-link.
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
### Basic Usage
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { AlarmService } from 'react-native-alarms/service';
|
|
56
|
+
|
|
57
|
+
// Check permissions
|
|
58
|
+
const permission = await AlarmService.checkPermission();
|
|
59
|
+
|
|
60
|
+
// Request permissions if needed
|
|
61
|
+
if (permission.status !== 'granted') {
|
|
62
|
+
await AlarmService.requestPermission();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Schedule an alarm for 10 minutes from now
|
|
66
|
+
const alarmId = await AlarmService.scheduleAlarm({
|
|
67
|
+
timestamp: Date.now() + 10 * 60 * 1000,
|
|
68
|
+
title: 'Wake up!',
|
|
69
|
+
body: 'Time to start your day',
|
|
70
|
+
vibrate: true,
|
|
71
|
+
snoozeEnabled: true,
|
|
72
|
+
snoozeMinutes: 5,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log('Alarm scheduled:', alarmId);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Listening to Alarm Events
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { AlarmService } from 'react-native-alarms/service';
|
|
82
|
+
|
|
83
|
+
// Listen for when alarm fires
|
|
84
|
+
const unsubscribeFired = AlarmService.onAlarmFired((alarm) => {
|
|
85
|
+
console.log('Alarm fired:', alarm.title);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Listen for when alarm is dismissed
|
|
89
|
+
const unsubscribeDismissed = AlarmService.onAlarmDismissed((alarm) => {
|
|
90
|
+
console.log('Alarm dismissed:', alarm.alarmId);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Listen for when alarm is snoozed
|
|
94
|
+
const unsubscribeSnoozed = AlarmService.onAlarmSnoozed((alarm) => {
|
|
95
|
+
console.log('Alarm snoozed:', alarm.alarmId);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Cleanup listeners when done
|
|
99
|
+
unsubscribeFired();
|
|
100
|
+
unsubscribeDismissed();
|
|
101
|
+
unsubscribeSnoozed();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Managing Alarms
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { AlarmService } from 'react-native-alarms/service';
|
|
108
|
+
|
|
109
|
+
// Get all scheduled alarms
|
|
110
|
+
const alarms = await AlarmService.getAllAlarms();
|
|
111
|
+
|
|
112
|
+
// Get a specific alarm
|
|
113
|
+
const alarm = await AlarmService.getAlarm(alarmId);
|
|
114
|
+
|
|
115
|
+
// Check if alarm is scheduled
|
|
116
|
+
const isScheduled = await AlarmService.isScheduled(alarmId);
|
|
117
|
+
|
|
118
|
+
// Update an alarm
|
|
119
|
+
await AlarmService.updateAlarm(alarmId, {
|
|
120
|
+
timestamp: Date.now() + 20 * 60 * 1000,
|
|
121
|
+
title: 'Updated alarm',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Snooze the currently ringing alarm
|
|
125
|
+
await AlarmService.snoozeAlarm(alarmId, 10); // Snooze for 10 minutes
|
|
126
|
+
|
|
127
|
+
// Stop the currently ringing alarm
|
|
128
|
+
await AlarmService.stopAlarm(alarmId);
|
|
129
|
+
|
|
130
|
+
// Cancel a specific alarm
|
|
131
|
+
await AlarmService.cancelAlarm(alarmId);
|
|
132
|
+
|
|
133
|
+
// Cancel all alarms
|
|
134
|
+
await AlarmService.cancelAllAlarms();
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## API Reference
|
|
138
|
+
|
|
139
|
+
### Types
|
|
140
|
+
|
|
141
|
+
#### `AlarmConfig`
|
|
142
|
+
Configuration object for scheduling alarms.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
type AlarmConfig = {
|
|
146
|
+
alarmId?: string; // Unique identifier (auto-generated if omitted)
|
|
147
|
+
timestamp: number; // Time in milliseconds (Date.now() format)
|
|
148
|
+
title: string; // Alarm title/label
|
|
149
|
+
body?: string; // Alarm description
|
|
150
|
+
sound?: string; // 'default' or custom sound file name
|
|
151
|
+
vibrate?: boolean; // Enable vibration (Android only)
|
|
152
|
+
snoozeEnabled?: boolean; // Allow snoozing
|
|
153
|
+
snoozeMinutes?: number; // Snooze duration in minutes
|
|
154
|
+
repeat?: AlarmRepeat; // Repeat configuration
|
|
155
|
+
data?: string; // Custom JSON string payload
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `AlarmRepeat`
|
|
160
|
+
Repeat configuration for recurring alarms.
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
type AlarmRepeat = {
|
|
164
|
+
type: 'none' | 'daily' | 'weekly' | 'interval';
|
|
165
|
+
weekdays?: number[]; // 1 = Sunday, 7 = Saturday (for weekly)
|
|
166
|
+
intervalMs?: number; // Interval in milliseconds (for interval type)
|
|
167
|
+
};
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### `Alarm`
|
|
171
|
+
Alarm object returned from queries.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
type Alarm = {
|
|
175
|
+
alarmId: string;
|
|
176
|
+
timestamp: number;
|
|
177
|
+
title: string;
|
|
178
|
+
body: string;
|
|
179
|
+
sound: string;
|
|
180
|
+
vibrate: boolean;
|
|
181
|
+
snoozeEnabled: boolean;
|
|
182
|
+
snoozeMinutes: number;
|
|
183
|
+
repeat: AlarmRepeat;
|
|
184
|
+
data: string;
|
|
185
|
+
enabled: boolean;
|
|
186
|
+
nextTriggerAt: number; // 0 if no future trigger
|
|
187
|
+
};
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### `AlarmPermission`
|
|
191
|
+
Permission status object.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
type AlarmPermission = {
|
|
195
|
+
status: 'granted' | 'denied' | 'notDetermined';
|
|
196
|
+
notifications: boolean;
|
|
197
|
+
canScheduleExact: boolean;
|
|
198
|
+
canDrawOverlays: boolean; // Android only
|
|
199
|
+
canUseFullScreenIntent: boolean; // Android only
|
|
200
|
+
backend?: string; // iOS only: 'alarmkit' or 'notifications'
|
|
201
|
+
};
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Platform-Specific Behavior
|
|
205
|
+
|
|
206
|
+
### iOS
|
|
207
|
+
- **iOS 26+**: Uses native AlarmKit for real alarms that bypass silent mode
|
|
208
|
+
- **iOS < 26**: Falls back to local notifications
|
|
209
|
+
- Always handles vibration through system settings
|
|
210
|
+
- Full-screen alarm display with system Stop/Snooze buttons
|
|
211
|
+
|
|
212
|
+
### Android
|
|
213
|
+
- Requires `SCHEDULE_EXACT_ALARM` permission for exact timing
|
|
214
|
+
- Uses full-screen notifications on lock screen
|
|
215
|
+
- Respects silent mode (can be overridden with system settings)
|
|
216
|
+
- Supports custom sounds from app bundle or file system
|
|
217
|
+
|
|
218
|
+
## Repeat Types
|
|
219
|
+
|
|
220
|
+
### None (One-time)
|
|
221
|
+
```typescript
|
|
222
|
+
{ type: 'none' }
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Daily
|
|
226
|
+
Rings at the same time every day.
|
|
227
|
+
```typescript
|
|
228
|
+
{ type: 'daily' }
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Weekly
|
|
232
|
+
Rings at the same time on specified days.
|
|
233
|
+
```typescript
|
|
234
|
+
{
|
|
235
|
+
type: 'weekly',
|
|
236
|
+
weekdays: [1, 3, 5] // Sunday, Wednesday, Friday
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Interval
|
|
241
|
+
Rings at regular intervals. Note: intervals reset if the app is killed.
|
|
242
|
+
```typescript
|
|
243
|
+
{
|
|
244
|
+
type: 'interval',
|
|
245
|
+
intervalMs: 3600000 // Every hour
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Complete Example
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
import React, { useEffect, useState } from 'react';
|
|
253
|
+
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
254
|
+
import { AlarmService } from 'react-native-alarms/service';
|
|
255
|
+
|
|
256
|
+
export function AlarmScreen() {
|
|
257
|
+
const [alarms, setAlarms] = useState([]);
|
|
258
|
+
const [permissions, setPermissions] = useState(null);
|
|
259
|
+
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
initializeAlarms();
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
const initializeAlarms = async () => {
|
|
265
|
+
const perms = await AlarmService.checkPermission();
|
|
266
|
+
setPermissions(perms);
|
|
267
|
+
|
|
268
|
+
if (perms.status !== 'granted') {
|
|
269
|
+
await AlarmService.requestPermission();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const allAlarms = await AlarmService.getAllAlarms();
|
|
273
|
+
setAlarms(allAlarms);
|
|
274
|
+
|
|
275
|
+
const unsubFired = AlarmService.onAlarmFired((alarm) => {
|
|
276
|
+
console.log('🔔 Alarm fired:', alarm.title);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const unsubSnoozed = AlarmService.onAlarmSnoozed((alarm) => {
|
|
280
|
+
console.log('😴 Alarm snoozed:', alarm.title);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return () => {
|
|
284
|
+
unsubFired();
|
|
285
|
+
unsubSnoozed();
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const scheduleAlarm = async () => {
|
|
290
|
+
const alarmId = await AlarmService.scheduleAlarm({
|
|
291
|
+
timestamp: Date.now() + 5 * 60 * 1000,
|
|
292
|
+
title: 'Time for a break!',
|
|
293
|
+
body: 'Take a moment to rest',
|
|
294
|
+
vibrate: true,
|
|
295
|
+
snoozeEnabled: true,
|
|
296
|
+
snoozeMinutes: 5,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const updated = await AlarmService.getAllAlarms();
|
|
300
|
+
setAlarms(updated);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
return (
|
|
304
|
+
<View style={styles.container}>
|
|
305
|
+
<Text style={styles.title}>Alarm Manager</Text>
|
|
306
|
+
|
|
307
|
+
<TouchableOpacity
|
|
308
|
+
style={styles.button}
|
|
309
|
+
onPress={scheduleAlarm}
|
|
310
|
+
>
|
|
311
|
+
<Text style={styles.buttonText}>Schedule Alarm</Text>
|
|
312
|
+
</TouchableOpacity>
|
|
313
|
+
|
|
314
|
+
<View style={styles.list}>
|
|
315
|
+
{alarms.map((alarm) => (
|
|
316
|
+
<View key={alarm.alarmId} style={styles.alarmItem}>
|
|
317
|
+
<Text>{alarm.title}</Text>
|
|
318
|
+
<Text>{new Date(alarm.timestamp).toLocaleTimeString()}</Text>
|
|
319
|
+
</View>
|
|
320
|
+
))}
|
|
321
|
+
</View>
|
|
322
|
+
</View>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const styles = StyleSheet.create({
|
|
327
|
+
container: { flex: 1, padding: 20 },
|
|
328
|
+
title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20 },
|
|
329
|
+
button: { backgroundColor: '#007AFF', padding: 12, borderRadius: 8 },
|
|
330
|
+
buttonText: { color: '#fff', fontWeight: 'bold', textAlign: 'center' },
|
|
331
|
+
list: { marginTop: 20 },
|
|
332
|
+
alarmItem: { padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee' },
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Troubleshooting
|
|
337
|
+
|
|
338
|
+
### "Alarm Native module is not linked"
|
|
339
|
+
Ensure the native module is properly linked:
|
|
340
|
+
```bash
|
|
341
|
+
cd ios && pod install && cd ..
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Alarms not triggering
|
|
345
|
+
1. Check permissions: `await AlarmService.checkPermission()`
|
|
346
|
+
2. Ensure app has necessary permissions:
|
|
347
|
+
- Android: `SCHEDULE_EXACT_ALARM`, `POST_NOTIFICATIONS`
|
|
348
|
+
- iOS: Allow notifications in Settings
|
|
349
|
+
|
|
350
|
+
### iOS-specific: Notifications instead of full-screen alarm
|
|
351
|
+
- Full-screen alarms (AlarmKit) require iOS 26+
|
|
352
|
+
- Older devices use local notifications
|
|
353
|
+
- Check `permission.backend` to see which is active
|
|
354
|
+
|
|
355
|
+
### Android-specific: Alarm doesn't ring when app is killed
|
|
356
|
+
- Enable Autostart permissions on device
|
|
357
|
+
- Check device's battery optimization settings
|
|
358
|
+
- Some OEMs require manual approval in their app management screens
|
|
359
|
+
|
|
360
|
+
## Contributing
|
|
361
|
+
|
|
362
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
363
|
+
|
|
364
|
+
## License
|
|
365
|
+
|
|
366
|
+
MIT © 2024 Suraj Prasad
|
|
367
|
+
|
|
368
|
+
## Support
|
|
369
|
+
|
|
370
|
+
For issues and questions, please visit:
|
|
371
|
+
- GitHub Issues: https://github.com/surajprasad13/react-native-alarms/issues
|
|
372
|
+
- Email: surajvishwakarma830@gmail.com
|
|
373
|
+
|
|
374
|
+
## Changelog
|
|
375
|
+
|
|
376
|
+
### v0.1.0
|
|
377
|
+
- Improved TypeScript support with proper type exports
|
|
378
|
+
- Added AlarmService convenience class
|
|
379
|
+
- Comprehensive documentation
|
|
380
|
+
- Fixed module linking issues
|
|
381
|
+
|
|
382
|
+
### v0.0.1
|
|
383
|
+
- Initial release
|
|
384
|
+
- Cross-platform alarm scheduling
|
|
385
|
+
- Event-driven architecture
|
|
386
|
+
- Permission management
|