Marco.org

I’m : a programmer, writer, podcaster, geek, and coffee enthusiast.

Courage

Many Apple fans were amused when Phil Schiller explained the removal of the headphone jack on last year’s iPhone as “courage”. But that was nothing compared to what happened last week.

For ten years, the iPhone looked like this:

A rounded rectangle, bars on top and bottom, and a circle centered in the bottom bar. If you want to get fancy, put a line in the top bar, too.

It’s so simple that even when children draw it, it’s instantly recognizable as an iPhone to most of the world’s population. Not just any phone — an iPhone, specifically.

As an app developer and fan, I was hoping that the long-rumored edge-to-edge iPhone screen would still be a rectangle, possibly even with room for a Home button on a narrower bezel, so I wouldn’t have to change my habits (or my app’s layout):

But that’s the unmistakable image of an Android phone. (Or a generic smartphone — same thing.)

Apple would’ve lost what the iPhone has had since its introduction: a unique, recognizable shape that distinguishes itself from all of the other boring rectangles out there.

Many are now speculating that Apple will find a way to get rid of the iPhone X’s top “notch” (officially called the “sensor housing”) as soon as they can, and that this is a temporary design meant only for a few years. But I don’t think so.

Many app developers are planning to hide the notch in the UI with black bars. But Apple explicitly says not to.

This is the new shape of the iPhone. As long as the notch is clearly present and of approximately these proportions, it’s unique, simple, and recognizable.

It’s probably not going to significantly change for a long time, and Apple needs to make sure that the entire world recognizes it as well as we could recognize previous iPhones.

That’s why Apple has made no effort to hide the notch in software, and why app developers are being told to embrace it in our designs.

That’s why the HomePod software leak depicted the iPhone X like this: it’s the new basic, recognizable form of the iPhone.

Apple just completely changed the fundamental shape of the most important, most successful, and most recognizable tech product that the world has ever seen.

That’s courage.

Overcast for iOS 11 coming soon

I’m sorry that I missed the iOS 11 launch for my fancy drag-and-drop update. It’s coming soon, but it’s not ready yet.

In Hello Internet episode 4, CGP Grey introduced a metaphor for work-life balance as four light bulbs — work, friends, family, and health — between which one can allocate 100 watts, total. So it’s possible to shine brightly in one area at significant cost to the others, or to try to have a mediocre spread between all of them.

Usually, I prioritize family and work, in that order, and my friends are pretty tolerant of my general neglect, but health gets left as a pretty low priority.

This summer, I decided I finally needed to devote significant time to health, and since my family always comes first, that mostly came at the expense of reduced work time.1 And iOS 11 has ended up requiring more changes and fixes than I expected.

So I have a great Overcast update for iOS 11 and iPhone X in progress, but it’s not done yet. I appreciate your patience, and I hope you’ll find it worth the wait.


  1. I’m fine. I just finally realized that the correct amount of exercise for a 35-year-old was probably not zero. ↩︎

What we need from Apple to make standalone Apple Watch podcast apps

The Apple Watch desperately needs standalone podcast playback, especially with the LTE-equipped Series 3, which was designed specifically for exercising without an iPhone.

Believe me, I’ve tried. But limitations in watchOS 4 make it impossible to deliver standalone podcast playback with the basic functionality and quality that people expect.

Deal-breaker: Progress sync

Unlike on iOS, Watch apps aren’t allowed to play audio in the background and continue running.1

The only way to continue playback in the background on watchOS 4 is to use the WKAudioFilePlayer API. This is unsuitable for podcast players in its current state for one big reason:

It takes audio playback out-of-process, suspending the host app indefinitely during playback, and does not wake up the host app to notify it of playback progress or other relevant events like pausing, seeking, or reaching the end of an episode.

Since most podcast listeners also listen on their iPhone, the Watch needs to sync each episode’s listening progress with its iPhone app or a web service. But if you reach the end of a workout and pause playback without launching the podcast app, such as with a headphone “pause” button, turning off your headphones, removing your AirPods, or using the Now Playing app on the Watch, there’s no guarantee that the podcast app will be notified of your progress anytime soon. So when the user later goes to the iPhone app to continue playback, progress will be lost, or episodes’ state (played, deleted, recommended, etc.) will be wrong.

Minimum fix: During WKAudioFilePlayer playback, wake the host app to let it record progress periodically (ideally at least every minute) and on state-change events, such as pausing, seeking, and reaching the end of a file.

Better fix: Let apps continue running in the background indefinitely while they’re playing audio with WKAudioFilePlayer, just as workout apps can, so they can track their own state.2

To achieve the minimum experience-quality level that Apple and Overcast customers expect, watchOS and WKAudioFilePlayer also need a few more changes:

Volume control API or widget

Overcast’s top request for the Watch app by far is volume control via the Digital Crown, both for iPhone and Watch playback (when I offered it). It’s especially necessary for standalone Watch playback, as there’s very little access anywhere in watchOS to the concept of the system volume level.

Fix: An API to set the volume level, or a system UI widget for volume control like iOS’ MPVolumeView.

The lack of volume control is especially damaging with watchOS 4’s great new “Auto-launch Audio Apps” setting. If you’re playing audio from an iPhone app and have its corresponding Watch app installed, that Watch app shows by default when your Watch screen activates. If you don’t have its Watch app installed, the built-in Now Playing app shows instead.

In the last few days since watchOS 4’s launch, I’ve had dozens of users tell me that they’ve uninstalled Overcast’s Watch app just to force the Now Playing screen to auto-launch instead, just so they could have quick access to volume control.

Output-device presence, switching

WKAudioFilePlayer will not play to the Watch’s built-in speaker — it only plays to headphones connected to the Watch via Bluetooth. If playback is attempted without headphones connected, WKAudioFilePlayer just silently fails to play, without returning any errors.

Making matters worse, there appears to be no way to reliably detect the presence or absence of a suitable Bluetooth output device to avoid this.

Another common user request for Watch audio apps is an AirPlay output control. The rise of AirPods has increased this need and exacerbated the output-device-presence issue, as their multi-device sharing behavior leads to less certainty by the user about which device they’re currently connected to, and a more frequent need to manually select them on the current device.

Minimum fix: Fix the error-reporting behavior of WKAudioFilePlayer when suitable play conditions aren’t met, and provide a way to detect the presence or absence of a suitable audio-playback device so our apps can relay this information to the user.

Better fix: Also provide a standard AirPlay UI control, possibly integrated with the volume control, again like MPVolumeView on iOS.

Next/previous-track commands

Podcast listeners expect previous- and next-track buttons on headphones, cars, and the Now Playing app to perform 30-second seek operations instead of changing episodes completely. On iOS, MPRemoteCommandCenter lets apps respond to these commands however they want.

WKAudioFileQueuePlayer provides no such customization, ignores previous-track commands, and forces next-track commands to skip to the next audio file, losing any progress in the current one — and if there isn’t a next file in the queue, it stops playback completely. And all of this happens without waking the host app.

Minimum fix: Wake the host app whenever the current queue item changes in WKAudioFileQueuePlayer.

Better fix: Bring MPRemoteCommandCenter or an equivalent to watchOS, and if the host app adds its own command handlers, disable the built-in WKAudioFileQueuePlayer behavior for previous-/next-track commands.

Data-transfer progress, speed

While some apps may be able to perform direct downloads of podcast episodes from the internet to the Watch, many will rely on transferring audio files from the iPhone to the Watch to ensure compatible formats, consistent timestamps, small files, or audio-processing features.

Transferring a podcast file to the Watch is a long-running task, often taking at least a few minutes per episode (and sometimes much longer), but the WCSessionFileTransfer class provides no progress information. So there’s no way for apps to inform users how long the transfers may take, or if they’re currently moving at all.

Minimum fix: Add a progress API on WCSessionFileTransfer.

Better fix: Add a progress API on WCSessionFileTransfer and provide actionable information if the transfer is currently paused or waiting for something, such as having other transfers ahead of it in a queue, or needing a different power or connectivity state.3

Additionally: Wi-Fi and LTE transfers to the Watch are currently much faster than Bluetooth, often by an order of magnitude, but the Watch seems to send all WCSessionFileTransfer data over Bluetooth even when connected to a power source. File transfers should use Wi-Fi when power allows.

Nice-to-have: Streaming audio playback

One of the most compelling features of the Series 3 Watch with LTE is streaming Apple Music playback, but there’s no streaming audio-playback API available to developers on watchOS today. Every method requires locally downloaded files.

I recognize this is a big task. That’s why it’s a “nice-to-have”.

Enhancement: Bring a relevant subset of AVPlayer to watchOS, or expose streaming-audio playback via some other method.


  1. There’s one elaborate exception that we discussed in Under The Radar #98: workout apps, which are allowed to run in the background and play audio. So this all becomes possible if you combine a standalone podcast player with a workout app, and only allow podcast playback while a workout is active that was started from that app. But this forces the combination of two completely different app types, and users would find the workout-during-playback requirement confusing, inexplicable, and limiting.

    Requiring podcast apps to also be workout apps is a user- and developer-hostile hack that Apple probably doesn’t intend. ↩︎

  2. This could also allow the use of the more capable in-process APIs such as AVAudioPlayer, which appeared to work well in watchOS 3. ↩︎

  3. While I have you, please also add this reporting for paused or waiting background NSURLSessionDownloadTask transfers. ↩︎