Update: Auto-tefilat harderech is live on Google play, now available also in English! download here.
Traveler’s prayer (image credits below)
In Jewish tradition, there is a prayer that is said when travelling: Tefilat HaDerech, the traveler’s prayer. It is recited only after you have left your city limits.
[Linguistic trivia: for you fantasy lovers, “Tefilat HaDerech” sounds similar to “ Kwisatz Haderach ” because Kwisatz Haderach is probably from Hebrew , it is similar to “Kfitzat HaDerech” — the leaping of the way or the shortening of the way. The suffix “-at” is a suffix meaning “of”.]
There is a fatal flaw in this concept: if you are driving alone, you need to stop about 1km after the city limits and recite the prayer. This is extremely impractical, and possibly even dangerous if you don’t find a safe place to stop. On the other hand, especially in these sad times, we really need all the prayers we can get.
One solution would be to recite the prayer before I leave. Not the best solution, but better than nothing.
Another solution is to carpool, and have my passenger recite the prayer. This can be difficult as I often travel at low-traffic times (not everyone can afford to arrive at work later or earlier than rush hour). It’s also difficult because not everyone wants to recite a prayer and I don’t want to make people feel uncomfortable riding with me.
So I’m creating an app that will recite the prayer at the time that I wish.
Features
It is possible to choose the voice (male or female), whether you are returning today (the prayer is slightly different if not) and of course, when you want it to be recited (e.g. 30 minutes from now).
My original idea was to use flutter_tts and text to speech, but it unfortunately doesn’t support Hebrew. Also, the text is known in advance, there isn’t actually a need for text to speech. I did try some other services, and I really didn’t like the robotic voice they produced. So I recorded myself for the female voice, and one of my sons (he’s a tenor :) ) for the male voice.
Not my son.
I’m using android_alarm_manager_plus for the delayed recitation. It’s a super easy plugin that gave me everything I could possibly want. Just set the correct prayer version as the alarm to play, and I’m done :). It also offers easy ways to check if an alarm has been set and to cancel it if so.
Code
First, the model:
//class representing the parameters for reciting a prayer at a later time.
class PrayerParameters {
//I created an enum instead of a bool because I like them. To each her own.
ReturnToday returnToday = ReturnToday.returnToday;
//In the future I want to add another voice type - user recording
VoiceType voiceType = VoiceType.female;
//time from now until prayer is recited
Duration time = const Duration(minutes: 30);
//to read at max volume or not? (sometimes I still use bools :))
bool maxVolume = false;
//the picker returns an int, easily turn it into a Duration
void setTime(int minutes) {
time = Duration(minutes: minutes);
}
//for debug
@override
String toString() {
return "$returnToday $voiceType $time";
}
}
And now the home page:
//in home_page.dart, on pressing the "Set prayer time" button
//get the prayer parameters
PrayerParameters? parameters = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
AlarmParametersPage()));
//if canceled, show snackbar and return
if (parameters == null) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Recitation not set")));
}
return;
}
//choose the correct mp3 file
String filename =
"${parameters.voiceType.name}-${parameters.returnToday.name}.mp3";
//create the alarm settings
final alarmSettings = AlarmSettings(
//ID for cancellation
id: Constants.alarmId,//42, the answer to all questions.
//when to play the file
dateTime: DateTime.now().add(parameters.time),
//put the filename we created before
assetAudioPath: 'assets/sounds/$filename',
//don't loop
loopAudio: false,
//don't vibrate
vibrate: false,
//do we set the volume to maximum for the recitation?
volumeMax: parameters.maxVolume,
//don't fade out
fadeDuration: 0,
//notification parameters
notificationTitle: "Traveler's prayer",
notificationBody: 'Speaking now',
//notify user if app is killed, this cancels the alarm in most phones
enableNotificationOnKill: true,
);
//set the alarm
bool success =
await Alarm.set(alarmSettings: alarmSettings);
As you can see, the alarm plugin makes things very easy. A notification automatically appears when the alarm is sounded — you don’t need to handle the notifications at all!
It also considerately outputs to the logcat the following on success:
I/flutter (13257): [Alarm] Notification with id 42 scheduled successfuly at 2023-12-07 15:37:24.955446Z GMT
I/flutter (13257): [Alarm] Alarm with id 42 scheduled successfully at 2023-12-07 15:37:24.955446
I/flutter (13257): [Alarm] NotificationOnKillService set with success
And if not, a clear error message (I got an error message that I needed a specific permission, for example).
My app checks if alarm alarmId
is set, and if so it provides a cancel
option:
//in home_page.dart, on pressing the "Cancel recitation" button
//easy cancel
bool success = await Alarm.stop(Constants.alarmId);
//notify user
if (mounted) {
if (success) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Canceled successfully")));
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Cancelation failed")));
}
}
And it is confirmed in the logcat again:
I/flutter (13257): [Alarm] Notification with id 42 canceled
I/flutter (13257): [Alarm] NotificationOnKillService stopped with success
In short, one of the easiest plugins it has been my pleasure to use.
And next
Still some minor bugs to iron out, but I hope to release this soon (and use it myself!). In the future, I will also support uploading your own recording, and more prayer versions — there are a number of different traditions.
Praying for better times.
Image created using Fooocus 2.1.824 running on a Windows computer, using prompt “A man standing at the side of the road with an open prayer book in his hands. The man is reading silently from the book. The road leads on to a beautiful landscape”. Fooocus is awesome , by the way.
Check out my free and open source online game Space Short. If you like my site, you can also buy me a coffee.