HeyClock- Android vs iOS

Work on the Android version of HeyClock is still running full steam ahead. However, I’ve definitely been presented with some head-scratchers when it comes to scheduling the alarms. Who would have thought that it would be easier to get a recurring event triggered from the background in iOS than in Android?

In iOS, the only reasonable way for me to trigger events regularly was to monitor the current time by watching the pings from the phone’s location services. When the timestamp matched the scheduled time of an event, I ran the code necessary to make the event happen. The location services monitoring code is allowed to run in the background, and so even with the phone in some sort of OS sleep mode, it still sees everything.

I’ve been spending time matching the Android data and layout to the iOS version- since working with iOS’s constraints system took up about 80% of the development time on HeyClock, I expected the Android version to go much more smoothly. And it did, in that aspect. I still need to tweak a couple things visually, but the layout is mostly finished.

HeyClock on iOS:

HeyClock on Android:

Back when I first started working on HeyClock, I read a little bit about scheduling events in Android, and it didn’t seem too difficult. In fact, it seemed like it was going to be WAY easier than in iOS- there were specific functions for scheduling an event to happen, and a special function specifically for making the events cut through a phone’s “sleep mode.”
Now that I’m actually working on it, though, I’m finding some issues. The test device I’m working with runs the oldest version of Android that HeyClock will run on (API 22, Android Lollipop), and I wasn’t expecting any issues at all getting scheduling to work since that version of Android didn’t even have the “Doze” sleep mode. However, it’s a Samsung Galaxy S5 Mini, and I guess it has some sort of manufacturer-specific power savings mode, because it’s definitely going out of its way to prevent certain services from starting until the phone’s screen has turned on- namely the Android Text-To-Speech service.

I went around and around, trying out different methods of starting the text-to-speech function in its own service, its own process, its own service AND process, and configuring those services and processes in different ways. Between that, and the fact that “Doze”-enabled phones only allow scheduled events to take place within particular “maintenance windows” (sort of defeats the purpose of scheduling them, doesn’t it?) it took some doing, but it looks like I’ve finally settled on a combination that works.

I’m using the AlarmManager setAlarmClock() function to use the phone’s built-in alarm clock manager to execute code at a given time (pretty close to that time, anyways; I don’t need millisecond precision). When it does, it automatically lets the app handle 10 seconds worth of execution before “putting it back to sleep” if it was in Doze mode. As soon as the alarm goes off, I start a foreground service with a wake-lock, and use that service to execute the Text-to-Speech stuff (since the TTS initialization sometimes takes a few seconds, it might not have finished by the end of the alarm clock’s 10-second window). I’ve tested this one after letting the phone sit motionless for 10 hours, which should have been plenty of time to force whatever internal Samsung sleep mode was preventing it from operating before- works perfect! Now, the real test will be to run it on a modern Android device (running at least API 28) to see what happens once Doze mode comes into play. I’ve got a used Motorola Moto G7 Power in the mail- being able to test it out in the oldest possible and newest possible Android versions will be absolutely necessary.