I want to create a React Native alarm application on Expo. I want the alarm to ring at the set time, whether I am in the app or not. The alarm should stop either when I press a stop button or when the user moves the phone. I can create events in the calendar using Expo Calendar. However, the alarm doesn't ring for a long time. It comes as a notification. The alarm should ring until the user dismisses it or moves the phone.
import React, { useEffect, useState } from "react";
import { TextInput, Text, TouchableOpacity, View, Button } from "react-native";
import DateTimePicker from "@react-native-community/datetimepicker";
import Icon from "react-native-vector-icons/Ionicons";
import * as Calendar from "expo-calendar";
const AddAlarm = () => {
const [date, setDate] = useState(new Date());
const [mode, setMode] = useState("date");
const [show, setShow] = useState(false);
const [value, onChangeText] = useState("");
const onChange = (event, selectedDate) => {
const currentDate = selectedDate;
setShow(false);
setDate(currentDate);
};
const showMode = (currentMode) => {
setShow(true);
setMode(currentMode);
};
const showDatepicker = () => {
showMode("date");
};
const showTimepicker = () => {
showMode("time");
};
const handleDatePicked = async () => {
const { status } = await Calendar.requestCalendarPermissionsAsync();
if (status !== "granted") {
alert("Takvim izni verilmedi!");
return;
}
const defaultCalendar = await Calendar.getCalendarsAsync();
const alarmTime = date.getTime();
const eventDetails = {
title: value,
startDate: new Date(alarmTime),
endDate: new Date(alarmTime),
timeZone: "local",
reminderMinutes: 0,
alarms: [{ relativeOffset: 0, method: Calendar.AlarmMethod.ALERT }],
};
await Calendar.createEventAsync(defaultCalendar[0].id, eventDetails);
console.log("Alarm set for:", date.toLocaleString());
};
useEffect(() => {
onChangeText("");
setDate(new Date());
}, []);
return (
<View
style={{
flex: 1,
}}
>
<TouchableOpacity
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
marginLeft: 10,
marginRight: 10,
height: 40,
marginTop: 10,
}}
onPress={showDatepicker}
>
{date ? (
<Text>{date.toLocaleDateString()}</Text>
) : (
<Text>Tarih Seçiniz</Text>
)}
<Icon name="calendar" size={30} color="gray" />
</TouchableOpacity>
<View
style={{
height: 1,
backgroundColor: "#ccc",
marginVertical: 10,
marginHorizontal: 10,
}}
></View>
<TouchableOpacity
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
marginLeft: 10,
marginRight: 10,
height: 40,
}}
onPress={showTimepicker}
>
{date ? (
<Text>{date.toLocaleTimeString()}</Text>
) : (
<Text>Saat Seçiniz</Text>
)}
<Icon name="calendar" size={30} color="gray" />
</TouchableOpacity>
<View
style={{
height: 1,
backgroundColor: "#ccc",
marginVertical: 10,
marginHorizontal: 10,
}}
></View>
<TextInput
editable
multiline
numberOfLines={4}
placeholder="Açıklama"
onChangeText={(text) => onChangeText(text)}
value={value}
style={{ padding: 10, borderWidth: 1, margin: 10, borderColor: "#ccc" }}
/>
{show && (
<DateTimePicker
testID="dateTimePicker"
value={date}
mode={mode}
is24Hour={true}
onChange={onChange}
/>
)}
<View
style={{
marginBottom: 50,
flex: 1,
position: "absolute",
bottom: 0,
left: 0,
right: 0,
justifyContent: "flex-end",
alignItems: "center",
}}
>
<Button onPress={handleDatePicked} title="Kaydet" />
</View>
</View>
);
};
export default AddAlarm;