Native alarm scheduling for React Native and Expo apps with Android exact alarms and iOS AlarmKit support
翻譯準備中
正在載入完整 README。
檢視完整 README ↗Real, user-visible alarms for React Native and Expo — AlarmKit on iOS, an equivalent on Android.
iOS 26 shipped AlarmKit: an alarm that rings on the lock screen, through silent mode and Focus,
whether or not your app is running. Android ships no such framework. This package gives you AlarmKit
on iOS and builds the equivalent on Android out of AlarmManager.setAlarmClock, a foreground service
that keeps ringing through Doze and a killed app, and a full-screen lock-screen ring UI — behind one
typed API.
Notification libraries schedule a notification and hope the device is awake to show it. This schedules an actual alarm.
openAppOnly, only completeNativeAlarmAsync() ends it.ACTION_SET_ALARM and ACTION_SHOW_ALARMS.NSAlarmKitUsageDescription.📖 Documentation — guides for scheduling, handoffs, and sounds.
llms.txt, raw markdown per page, and a bundled agent skill.Bare React Native apps need Expo Modules installed first.
npm install react-native-alarm-scheduler
Add the config plugin to your app config, then rebuild:
{
"expo": {
"plugins": [
[
"react-native-alarm-scheduler",
{ "alarmKitUsageDescription": "Allow this app to schedule alarms." }
]
]
}
}
npx expo prebuild
npx expo run:android
All plugin options are listed in the installation docs.
import AlarmScheduler from 'react-native-alarm-scheduler';
const permissions = await AlarmScheduler.requestPermissionsAsync();
if (permissions.canScheduleExactAlarms) {
const alarm = await AlarmScheduler.scheduleAlarmAsync({
hour: 7,
minute: 30,
title: 'Morning alarm',
weekdays: [1, 2, 3, 4, 5], // ISO: 1 = Monday, 7 = Sunday
});
await AlarmScheduler.cancelAlarmAsync(alarm.id);
}
List and cancel what you scheduled:
const alarms = await AlarmScheduler.getScheduledAlarmsAsync();
for (const alarm of alarms) {
await AlarmScheduler.cancelAlarmAsync(alarm.id);
}
Events (onAlarmTriggered, onAlarmAction, onAlarmStateChange) fire only when a JS runtime is
alive — which it is not on a cold launch from the lock screen. Everything they carry is also written
natively before any JS runs, so reconcile from the async getters on every launch and foreground:
const handoff = await AlarmScheduler.getPendingNativeAlarmHandoffAsync();
const context = handoff ? null : await AlarmScheduler.getCurrentAlarmContextAsync();
const alarmId = handoff?.alarmId ?? context?.id;
if (alarmId) {
router.replace(`/alarm/${alarmId}`);
await AlarmScheduler.clearPendingNativeAlarmHandoffAsync();
}
See the API reference.
Set alertActionMode: 'openAppOnly' and the ringing alert loses its stop button — the only way out
opens your app, and the alarm keeps ringing until you call completeNativeAlarmAsync(alarmId).
Useful when "the user pressed stop" is not proof of anything:
await AlarmScheduler.scheduleAlarmAsync({
hour: 7,
minute: 0,
title: 'Wake up',
// Android inherits every shared iOS field; set android only where platforms differ.
ios: { alertActionMode: 'openAppOnly', stopIntentBehavior: 'rescheduleImmediate' },
android: { maxRingDurationSeconds: 0 },
});
The guarantee is absolute on Android and best-effort on iOS — see Completion gating.
以上為 README 的開頭部分。其餘內容請閱讀原文。 檢視完整 README ↗