Why this app exists
In this category, trust is the product.
Read the reviews of the existing apps and the same complaints keep coming back: full-screen advertising in a religious context, a location-data resale scandal still cited years later, prayer times that do not match the local mosque, sacred content put behind a paywall, and the call to prayer that simply does not sound.
Qindil answers each one: no advertising, no account, no server, seven calculation methods with per-prayer fine adjustment, nothing locked, and local notifications treated as the main feature rather than a detail.
The promise holds because it is literal in the code: exactly one network stream exists, the recitation audio. We cannot sell your data, because we do not have it.
The engineering challenges
Sixty-four notifications, and a system that drops the rest without a word.
The notification budget, the worst failure of all. Four independent schedulers together requested far more triggers than iOS allows. The system keeps the nearest ones and silently discards the surplus without returning any error: in practice the prayers furthest out were the ones being dropped, which is the product's number one promise, while the internal counter recorded them as scheduled successfully. A purpose-built allocator now shares the budget by priority, prayers first, and reads the real state of the queue instead of guessing it, including triggers placed by code that is not its own.
The permanent black screen. There was no error boundary anywhere in the app. In a release build, an exception during render does not produce a native crash: the tree unmounts, the screen stays black for good, and nothing surfaces in Apple's tooling. Two levels were added, one at the root and one around navigation, with colours hard-coded, because the fallback screen has to render even when the theme is precisely what just fell over.
Real streaming, obtained by patching native code. The audio library downloaded the entire file before playing the first second. A patch applied to the dependency switches remote playback to true streaming. In the same pass the player's races were closed: the re-entrance guard landed after two awaits, so two quick taps would announce one surah while another was playing. A phone call now becomes a resumable pause instead of a jump to the next track.
A phantom microphone and phantom photos in the binary. The audio library shipped a complete recorder, and another dependency referenced the Photos framework. Those symbols alone are enough for Apple's static analysis to conclude the app touches the microphone and to refuse the upload, for want of a purpose string we could not have written honestly since nothing records. Both were neutralised by patching the dependencies: a release build validated on a real iPhone would never have revealed the problem.
Failure paths that lie. A denied notification permission resolves normally instead of throwing, so the schedulers quietly gave up while the settings screen showed switches turned on that triggered nothing. A download intercepted by a captive portal answers with a success code, and a web page ended up renamed as an audio file, green tick and all. Beyond the polar circle the calculation engine returns non-numeric values for several weeks a year. The happy path was sound: it was the failure paths that had to be rewritten.
The one thing that cannot be fixed at the keyboard. The translation, the recitation and the calligraphic typeface originally considered are all under licences restricted to non-commercial use. The real risk is not litigation, it is Apple's review, which can ask for written authorisation. That finding is what moved the whole model to being entirely free with nothing locked and an optional way to support the work: non-commercial use becomes defensible again, and Apple's privacy questionnaire can answer "data not collected" without lying.