It's been a couple of weeks since I stopped working on my side project, Woo Cow Time. Unfortunately I hit enough roadblocks that the app doesn't seem feasible to build for iOS, so I've given up on it for now.
But I did spend another weekend on it before I gave up, so here's an update on what I tried, and where I got stuck.
If you read about Day 1 of working on Woo Cow Time, you'll know it's a cow-themed-Australian-tinged-workout app that lets you combine timed and untimed exercises into the same workout.
As some follow-up from my post about getting started with Woo Cow Time, someone pointed out that I didn't mention this bodyweight fitness app made by a member of the Reddit community I got my workout from. That app doesn't allow for customisation of the workout, apart from skipping sections, and I also find the UX really confusing. I should have explained earlier why that one isn't a good fit for me, since it's created specifically for the workout I do.
Moving on, here's how my second weekend of working on Woo Cow Time went.
After one day of work I had a very minimal Minimum Viable Product, so I took it for a spin. As I was working out I noticed a few crucial features and behaviours that were missing.
I hadn't added audio indicators to tell you when the next exercise starts, so I had to keep checking the phone screen to figure out when to move on. Very awkward, but easily fixed by adding some beeps for the last few seconds of a timed exercise and a different beep when the exercise changes.
A bigger issue was that the timer would stop anytime the screen went off or I switched to a different app. I like to spend my workout breaks (which are timed by the app) catching up on reading articles on my phone, so it's critical that I can switch apps while the timer keeps running. And obviously it needs to keep running if the phone screen turns off, or else it should force the screen to stay on.
Keeping the timer running in the background proved nigh on impossible. I searched high and low for suggestions on this, but none of them seemed to work for me.
One suggestion was to register for the audio background mode used by music player apps, then play an audio file of silence constantly during the workout so the app would keep running in the background. This isn't a great solution, and may even give me trouble in having the app approved by Apple, but I also couldn't get my timer to keep running, even if I did get audio to play while my app wasn't in the foreground.
Another suggestion was to schedule the beeps and audio cues when the app leaves the foreground, and to play them at the right times without having a timer running in my UI at all. Sort of like a playlist of audio cues. This could work for an app that only has timed exercises, but mine lets you mix in untimed exercises as well. When there's an untimed exercise, after the audio cue to start the exercise, the user would need to return to the app to tap a button indicating that they'd finished the exercise. If the next exercise was timed (say it's a timed break) and the user switches to another app immediately, I could again cue up a new timed playlist of audio cues up until the next untimed exercise. Maybe this would work, but I was unconvinced, as it seems like a hack that could easily get out of time or otherwise not match the user's expectations.
Someone suggested I try using HealthKit's
HKWorkoutSession, which lets your app run in the background while you're creating the workout. Unfortunately, this is only the case for Apple Watch apps. I'm yet to discover any Apple-sanctioned way to run a workout app in the background on an iPhone. I also hadn't considered using HealthKit in this way earlier, because I wanted HealthKit syncing to be optional, not required, but it seems like you can create a HealthKit workout object and then not write it to HealthKit when the workout is finished, so this approach could maybe work for me.
I thought I might add a Watch app to Woo Cow Time eventually, so I didn't hate the idea of having to use WatchKit to get the behaviour I wanted. I spent most of Sunday putting together an Apple Watch version of the app, ready to test on Monday morning.
I was able to reuse a lot of the code I'd written for playing system sounds and speaking the names of exercises, and switching some audio cues to use the Watch's haptics engine only took minor tweaks. This blog post came in handy for understanding how the haptics work, and what options are available.
I had a list of things I wanted to add next to the Watch app that I was going to finish off this post with, but I hit a snag as soon as I tested the app on Monday morning. I had wrongly assumed that when I had Bluetooth headphones connected to my iPhone, the Watch's audio would also be routed through my headphones. But it's not—it comes straight out of the Watch speaker. This is a deal-breaker for me, because I workout while other people are sleeping, and wear headphones for that reason. I also want my music to be ducked when the app is playing audio cues so I can hear them properly, but this isn't possible when the audio cues play from a different device to the music.
I haven't been able to find any way to send the Watch app's audio cues to the phone instead so far, and without the audio cues, you'd have to keep waking up your Watch to check the screen for which exercise you should be doing. I may look into whether I can make the Watch app tell the iPhone app to play the audio cues, but I'm concerned about the lag that might introduce. I've already noticed lag issues with text-to-speech for saying the exercise names (and "halfway" when you hit the mid-point of a timed exercise). The text-to-speech for the next exercise's name shouldn't really come any earlier than about 5 or 6 seconds before the end of the current exercise, but if I want to have beeps at 3, 2, and 1 second to go, and a different beep when the next exercise starts, there's very little room to account for lag after queuing up the text-to-speech at 6 seconds to go. It may not be impossible, but it doesn't seem like a solid approach to this problem.
At this point the app seems like a doomed experiment, due to the specific requirements I have for it and Apple's restrictions for running an iPhone app in the background. If I come across any ideas that might save it, I'll post an update on future efforts to make it work.
If you have any ideas of approaches I've not thought of, please let me know! You can find me on Micro.blog at micro.blog/belle or email me at belle at hellocode dot co.