PodSearch

Under the Radar

143: Implementing Step-Counting

 

00:00:00 ◼   ► Welcome to Under the Radar, a show about independent iOS app development.

00:00:04 ◼   ► I'm Marco Arment.

00:00:05 ◼   ► And I'm David Smith.

00:00:07 ◼   ► Under the Radar is never longer than 30 minutes, so let's get started.

00:00:11 ◼   ► So a couple of weeks ago, we did an episode where Marco talked through the complexity

00:00:18 ◼   ► and underpinnings of the new search system that he built into Overcast.

00:00:21 ◼   ► And it was kind of surprising to me that the feedback I got from a lot of people about

00:00:26 ◼   ► that show was that they really liked it.

00:00:28 ◼   ► And what was especially interesting was that a lot of that feedback was from people who

00:00:32 ◼   ► are not particularly technical, aren't people who are necessarily going to ever implement

00:00:36 ◼   ► a search system.

00:00:37 ◼   ► Because I know there's a lot of people who listen to the show more for the businessy

00:00:40 ◼   ► or marketing types of topics rather than the technical topics, but there are a lot of people

00:00:46 ◼   ► who really enjoy that.

00:00:47 ◼   ► And I think there is something to just hearing someone break down a really complicated problem

00:00:53 ◼   ► that is a good exercise and a helpful thing for us to do to just encourage our own brains

00:01:01 ◼   ► to be good at thinking and to think of, you know, sort of, you may not encounter that

00:01:05 ◼   ► exact problem, but it may be useful.

00:01:07 ◼   ► And so in that same vein, I'm going to, this week, largely unpack something that I've been

00:01:12 ◼   ► struggling with that falls into the same kind of category of something that is superficially

00:01:17 ◼   ► pretty easy but is actually fiendishly complicated.

00:01:20 ◼   ► And that is this week, I've been forced to essentially rebuild the step engine in Pedometer++.

00:01:27 ◼   ► It turns out that there is an issue and a bug in iOS 12.

00:01:30 ◼   ► I don't know if it's a bug.

00:01:32 ◼   ► There's a change in iOS 12, that's the charitable way to say it, in the way that CoreMotion

00:01:37 ◼   ► reports steps that are from a few days ago, and it causes it to sort of significantly

00:01:42 ◼   ► undercount versus the health app, and it's causing lots of consternation and problems

00:01:47 ◼   ► that I'll get into.

00:01:49 ◼   ► But this change is one of these things that for a while I've kind of had ways that I'm

00:01:51 ◼   ► working around and they kind of have been patched around, weird quirks in CoreMotion,

00:01:56 ◼   ► but I just can't do that anymore.

00:01:57 ◼   ► So I have to rebuild it, and I'm moving it to a system that is based largely on health.

00:02:03 ◼   ► But the process of doing this is something that seems relatively, that should be relatively

00:02:08 ◼   ► straightforward, but it's actually not at all.

00:02:12 ◼   ► And it's, you know, this week has been just, I've been joking with my wife that I feel

00:02:16 ◼   ► like I'm spending half my time just sitting at my desk thinking.

00:02:21 ◼   ► If you've ever read the stories of Winnie the Pooh, where he goes to his thoughtful

00:02:25 ◼   ► spot and he sits and he taps his forehead and says "think, think, think," that has been

00:02:29 ◼   ► me all week, because there's so many of these nuances and challenges that take something

00:02:34 ◼   ► that superficially should be relatively straightforward and turns out to actually be not.

00:02:40 ◼   ► You have to make tremendous amounts of complicated decisions and there's compromises, and you

00:02:45 ◼   ► end up in situations where you can't do two things, it becomes impossible, and I don't

00:02:50 ◼   ► like using the word "impossible" generally, but as best I can tell, there is no way to

00:02:56 ◼   ► reconcile certain goals or desires that you have, and I think that makes solving problems

00:03:01 ◼   ► like this the interesting part of what we do.

00:03:04 ◼   ► The displaying of the data or those types of things, the UI parts, it's fun and it's

00:03:09 ◼   ► interesting, but this is where the real rubber meets the road and things get hard.

00:03:14 ◼   ► I honestly kind of enjoy this kind of problem.

00:03:17 ◼   ► Whenever I'm in it, I find that's kind of like the good work of a programmer.

00:03:23 ◼   ► That's kind of like the work that we wait for, because so often what we have to work

00:03:25 ◼   ► on is boring or tedious or "oh, the login screen needs to accept this new condition,"

00:03:31 ◼   ► like that's really boring.

00:03:33 ◼   ► But when you have a hard problem to solve, it activates a part of my brain that is curious

00:03:39 ◼   ► and loves challenges and loves to be flexed in that way.

00:03:43 ◼   ► If you're lucky as a programmer, you get that maybe 10% of the time, and usually not even

00:03:47 ◼   ► that much.

00:03:48 ◼   ► >> Yeah, so anyway, without further ado, let's get started on the actual problem I'm facing.

00:03:54 ◼   ► So first, it's probably good to start with, like at its core, what I try and do in Pedometer++

00:03:59 ◼   ► is I'm answering the question, "How many steps did you take today?"

00:04:04 ◼   ► Like at its core, that is what the app is trying to do.

00:04:07 ◼   ► So of course, then you have to ask the question, "Well, what is a step?"

00:04:11 ◼   ► And I suppose intuitively, I think everyone has an understanding of what a step is.

00:04:15 ◼   ► It's the thing you've been doing since you were one year old, where you take one of your

00:04:20 ◼   ► legs and move it forward to the other one, you take another step, you move the other

00:04:24 ◼   ► leg forward.

00:04:25 ◼   ► Conceptually, I think that's something that people understand.

00:04:29 ◼   ► And what's complicated, though, is that turning that physical action into something that you

00:04:36 ◼   ► measure and can track and count is very difficult.

00:04:41 ◼   ► And thankfully, I'm not someone who's actually doing the work to build the physical monitoring

00:04:47 ◼   ► to do this, like the geniuses at Apple who make the motion coprocessor, or the people

00:04:51 ◼   ► at Fitbit, or the people who actually are doing the work, you know, looking at raw accelerometer

00:04:56 ◼   ► data and turning that into steps.

00:04:59 ◼   ► Because the reality is, based on where you are wearing your monitor, what terrain you

00:05:03 ◼   ► are working on, how fast you are going, what you're carrying in your hands, all of those

00:05:08 ◼   ► things dramatically impact what will be considered a step for the purposes of something that

00:05:15 ◼   ► is being counted.

00:05:17 ◼   ► And so there is no truth, then, about how many steps you took.

00:05:24 ◼   ► And this is something that I think I have many customers who really get wrapped around

00:05:29 ◼   ► the axle with, is that they want to have the sense that they took a certain number of steps,

00:05:36 ◼   ► the physical thing that they did out in the world, and they wanted that to translate into

00:05:41 ◼   ► a consistent measured value on their device.

00:05:45 ◼   ► That is impossible.

00:05:47 ◼   ► Like the classic example I have is people who go to a track and go for a walk.

00:05:52 ◼   ► They walk around a track, perfectly level, flat, like nothing complicated environment.

00:05:58 ◼   ► They walk around the track, you know, say they walk ten times around the track, and

00:06:02 ◼   ► one day it gives them a certain number of steps, and the next day it will give them

00:06:04 ◼   ► a different number of steps.

00:06:06 ◼   ► And it's just the nature of the problem of the exact nuances of how they walked, or even

00:06:11 ◼   ► more complicated is when they walk with somebody, say their spouse, and they're like, "I got

00:06:14 ◼   ► more steps than they did," and then they have to account for where are they holding their

00:06:18 ◼   ► phone in their pocket, what differences in heights, in gates, all manner of things.

00:06:23 ◼   ► And sometimes they're even wearing multiple devices, which makes it even doubly complicated.

00:06:28 ◼   ► So the one that I care about the most is people who have an iPhone and an Apple Watch.

00:06:33 ◼   ► They're both generating step numbers, but in either case, are those ever going to be

00:06:38 ◼   ► the same?

00:06:40 ◼   ► The truth that I have found in general is working with steps is that all we have is

00:06:46 ◼   ► just the numbers that the monitors spit out, and then we just have to work with those as

00:06:50 ◼   ► best we can.

00:06:51 ◼   ► So you're starting with something that's already kind of squishy, which isn't great.

00:06:57 ◼   ► And then the second part is understanding what do I mean by today, or having a sense

00:07:02 ◼   ► of timing and timeliness for those steps.

00:07:06 ◼   ► And we all know that the four hardest problems in computer science are naming, caching, syncing,

00:07:09 ◼   ► time zones, and off-by-one errors.

00:07:12 ◼   ► Those are the problems that really get hard.

00:07:14 ◼   ► And unfortunately, the step counting thing includes three of those, caching, syncing,

00:07:19 ◼   ► and time zones, because I have to deal with those.

00:07:24 ◼   ► But the one that's most complicated for the concept of today is, of course, time zones,

00:07:29 ◼   ► because you take your steps in time.

00:07:33 ◼   ► Say I measured all times GMT, and you then need to somehow tie that back to the concept

00:07:40 ◼   ► of a day.

00:07:42 ◼   ► And maybe that's reflecting the current time zone that the user is in when you're looking

00:07:47 ◼   ► at the steps, but then what should happen to steps you took in the past?

00:07:52 ◼   ► Or maybe you should have it be tied to the time that the app first saw that step, the

00:07:58 ◼   ► first time it measured it, and then you could tie it to a logical day.

00:08:03 ◼   ► And if you're curious, this is sort of what the activity app does.

00:08:06 ◼   ► The activity app, so if you have an Apple Watch, you get the activity app, and it has

00:08:09 ◼   ► its rings that measure your stand, exercise, and move.

00:08:14 ◼   ► And they show that based on the time zone your Apple Watch was set to when that action

00:08:20 ◼   ► took place, which can lead to really weird things like your stand hours, where if you

00:08:27 ◼   ► go on a transpacific flight from Australia to California, depending on which direction

00:08:34 ◼   ► you're going, your day could either not exist at all or potentially could last for 36 hours,

00:08:43 ◼   ► or really strange and complicated things.

00:08:44 ◼   ► But that's the way that they do it.

00:08:45 ◼   ► But it's kind of a cheat, because Apple's always running, so they always know the time

00:08:50 ◼   ► zone you're in when the steps are taken.

00:08:52 ◼   ► Whereas third-party apps don't have that benefit.

00:08:55 ◼   ► All we get is to be able to get run whenever the user opens us, for the most part.

00:09:03 ◼   ► Monjolo Background App Refresh, which helps but still isn't reliable.

00:09:06 ◼   ► So generally speaking, what I do is I show steps based on the current time zone.

00:09:12 ◼   ► And this is the same thing that the Health app does, coincidentally.

00:09:16 ◼   ► It's always updated to do essentially 24-hour periods that extend back in time based on

00:09:24 ◼   ► midnight in your current time zone.

00:09:27 ◼   ► That's basically what they do.

00:09:28 ◼   ► Which is great.

00:09:29 ◼   ► And that works reasonably well, but gets complicated by how you should then store your data.

00:09:37 ◼   ► Because if you're going to be able to dynamically change time zones, you need to be able to

00:09:42 ◼   ► store time zones in a way that you can re-chunk it based on changes in time zone.

00:09:48 ◼   ► So a naive solution would probably be to just store it, maybe steps per hour.

00:09:53 ◼   ► Which is actually the first version of the way that I did this, which turned out to be

00:09:56 ◼   ► problematic.

00:09:58 ◼   ► And this is quoting from Wikipedia.

00:09:59 ◼   ► "New Finland, India, Iran, Afghanistan, Burma, Sri Lanka, and the Marques, as well as parts

00:10:05 ◼   ► of Australia, use half-hour deviations from standard time for their time zones.

00:10:10 ◼   ► And certain nations, such as Nepal and the Cheltenham Islands of New Zealand, instead

00:10:14 ◼   ► use quarter-hour deviations."

00:10:16 ◼   ► Oh my god.

00:10:18 ◼   ► So time zones, right?

00:10:19 ◼   ► They're great.

00:10:20 ◼   ► So if you store in hour-long chunks, then you have this issue if you go to Newfoundland

00:10:27 ◼   ► or Sri Lanka or parts of Australia or the Cheltenham Islands, and suddenly you can't

00:10:33 ◼   ► accurately adjust it.

00:10:35 ◼   ► What I ended up doing is quarter-hour chunks.

00:10:39 ◼   ► So for every day, I store, I think it's 96 chunks, if my math's right, there.

00:10:44 ◼   ► But I essentially, for every 15-minute period in GMT, I store the number of steps you take.

00:10:52 ◼   ► And that mostly works for the concept of what today is.

00:10:58 ◼   ► Obviously, that gets really complicated and it's awkward, and I have to store way more

00:11:03 ◼   ► data than is really practical in some ways, but that's what I have to do.

00:11:10 ◼   ► And just keep this in the back of your mind when I start to get to things like syncing

00:11:15 ◼   ► and caching and those types of issues where it isn't just that I have one data point

00:11:20 ◼   ► that I need to deal with, I have every 15-minute data points spanning back potentially for

00:11:27 ◼   ► years for users.

00:11:30 ◼   ► And then one last thing that gets really fun with time zones, and in general the concept

00:11:35 ◼   ► of what a day is, is when you introduce things like goals and streaks into the application,

00:11:42 ◼   ► which is like a core feature, like number one feature of Phenomena++, is that you can

00:11:46 ◼   ► set a goal, for most people say it's 10,000 steps, and when you hit the goal, like the

00:11:52 ◼   ► app Cheer, Confetti comes down, it's very exciting, and a poor part of the app is that

00:11:56 ◼   ► you are trying to hit your goal every day.

00:12:00 ◼   ► And if you may have noticed, day, as I just explained, is this impossible concept that

00:12:06 ◼   ► doesn't mean anything.

00:12:08 ◼   ► And so what should happen if you hit your goal, you have a great streak going, you have

00:12:11 ◼   ► a 90-day streak, you're really proud of it, and then you fly to Europe, and suddenly all

00:12:17 ◼   ► of your concept of days have shifted, and especially if you tend to do your walking

00:12:23 ◼   ► at the beginning or end of a day, suddenly you may or may not actually have that streak.

00:12:28 ◼   ► And you have to answer the question, "Well, what do you do?

00:12:30 ◼   ► Should I store somehow the concept of goal achievements by logical days, for like September

00:12:38 ◼   ► 7th, 2018 is a day, and did you hit your goal on that?"

00:12:43 ◼   ► Well, if I do that, then I have the problem that I talked about before, where then I need

00:12:46 ◼   ► to know, "Well, how many steps did you take?"

00:12:48 ◼   ► Or is it just that you did hit your goal, but then how would I show that in the app?

00:12:52 ◼   ► And if I don't adjust it to the current time zone, then you have weird issues where what

00:12:56 ◼   ► happens if you do the transpacific flight where they miss a day, should that break their

00:13:00 ◼   ► streak?

00:13:01 ◼   ► Like if a day didn't actually exist, or they didn't take any steps?

00:13:06 ◼   ► So in that case, right now what I just do is I just show everything in the current time

00:13:10 ◼   ► zone, and unfortunately sometimes that means you miss your goal, because that is the least

00:13:15 ◼   ► worst, most understandable option that I've been able to find.

00:13:20 ◼   ► See I think what I would do is actually store per logical day whether you hit your goal,

00:13:29 ◼   ► because your goal can change also.

00:13:31 ◼   ► Like if I raise my goal, and I didn't reach the raised level last week, then I lose my

00:13:38 ◼   ► streak.

00:13:39 ◼   ► You know?

00:13:40 ◼   ► So I think what I would do is I would literally store for every known day of past data, I

00:13:45 ◼   ► would store whether that day's goal was reached, maybe for the sake of it, what that day's

00:13:48 ◼   ► goal was, and then I would also store the number of logical steps I've assigned to

00:13:54 ◼   ► that day, and that way it never changes.

00:13:56 ◼   ► And so suppose you get launched for the first time, and you haven't been launched for

00:14:00 ◼   ► seven days, but you have data before that.

00:14:03 ◼   ► You can then calculate those past seven days in local time, save them, and then basically

00:14:08 ◼   ► once a day is quote "done," you never revisit it.

00:14:11 ◼   ► Does that make sense?

00:14:13 ◼   ► Sure.

00:14:14 ◼   ► It's a reasonable approach.

00:14:16 ◼   ► And this is the thing that is so fiendish about this, is the approach you're describing,

00:14:21 ◼   ► where the works, but except for on the boundaries between long periods where you don't open

00:14:27 ◼   ► the app, and can also get complicated during those seven days in your example.

00:14:34 ◼   ► That user may have traveled dramatically, potentially, right?

00:14:40 ◼   ► And so then suddenly the concept of which day those steps were part of may not actually

00:14:46 ◼   ► be meaningful or make sense or be reasonable to them.

00:14:50 ◼   ► That they'll look at it and say, "Well, if you take a look at the steps in the current

00:14:53 ◼   ► time zone, it sort of makes sense, but it can be very inconsistent."

00:14:59 ◼   ► And one thing that I've learned is that people get really annoyed when the data doesn't

00:15:03 ◼   ► make sense to them.

00:15:05 ◼   ► That if I'm bucketing days into logical days, like the activity app approach, if I could

00:15:15 ◼   ► do that on a regular basis, I think it would work great.

00:15:18 ◼   ► Or, and this is something that I found, probably one of my longest-running health kit radars,

00:15:22 ◼   ► is if Apple stored the user's time zone when they took the steps that are recorded in health,

00:15:28 ◼   ► that would solve a lot of this problem.

00:15:30 ◼   ► But in the absence of that, what I find is that it ends up with these weird complications

00:15:34 ◼   ► where they look at the data and they're like, "Why is this day double-counted depending

00:15:40 ◼   ► on how you change time zones?"

00:15:43 ◼   ► Or "Why is this day missing?" for example.

00:15:45 ◼   ► That could also be problematic.

00:15:46 ◼   ► So it's like, your instinct is not wrong.

00:15:49 ◼   ► That's the thing.

00:15:50 ◼   ► Both of these answers are correct.

00:15:51 ◼   ► It's like they're both just different and lead to different sets of compromises or problems

00:15:55 ◼   ► that we just have to deal with as a result.

00:16:00 ◼   ► We are sponsored this week by Linode.

00:16:02 ◼   ► With Linode, you'll have access to a suite of powerful hosting options with prices starting

00:16:06 ◼   ► at just $5 a month.

00:16:07 ◼   ► You can be up and running with your own virtual server in the Linode cloud in under a minute.

00:16:11 ◼   ► Whether you're just getting started with your first server or you're deploying a more complex

00:16:15 ◼   ► system like what David and I run, Linode is the right choice for you.

00:16:19 ◼   ► They offer the fastest hardware, the fastest network, and the best customer support behind

00:16:24 ◼   ► it all.

00:16:25 ◼   ► It has never been easier to launch and maintain a Linode cloud server.

00:16:29 ◼   ► Linode also guarantees 99.9% uptime for server availability.

00:16:33 ◼   ► Once your server is up, they keep it that way.

00:16:35 ◼   ► And Linode now offers additional storage too.

00:16:37 ◼   ► Block storage is now out of beta and available almost everywhere.

00:16:41 ◼   ► So check it out today.

00:16:42 ◼   ► Linode is great for things like hosting large databases, running mail servers, operating

00:16:46 ◼   ► a VPN, Docker containers, private Git servers, entire applications like what I do, and so

00:16:51 ◼   ► much more.

00:16:52 ◼   ► And they are hiring right now.

00:16:54 ◼   ► If this interests you, go to Linode.com/careers.

00:16:56 ◼   ► Anyway, Linode has fantastic pricing options for their hosting.

00:17:01 ◼   ► Plans start at one gig of RAM for just $5 a month.

00:17:04 ◼   ► And there's lots of plans above that for all your various needs.

00:17:06 ◼   ► They also include things like high memory plans.

00:17:09 ◼   ► They start at 16 gigs of RAM and go up from there.

00:17:11 ◼   ► Listeners of this show can sign up at Linode.com/radar.

00:17:15 ◼   ► This will support us and get you $20 towards any Linode plan.

00:17:19 ◼   ► So on the one gig plan, that could be four months for free.

00:17:21 ◼   ► And with a seven day money back guarantee, there's nothing to lose.

00:17:25 ◼   ► So go to Linode.com/radar to learn more, sign up, and take advantage of that $20 credit

00:17:30 ◼   ► or use promo code radar2018 at checkout.

00:17:33 ◼   ► Thank you so much to Linode for supporting this show and Relay FM.

00:17:37 ◼   ► So let's just say we move past the concepts of time and space and instead focus on the

00:17:44 ◼   ► practical issues of actually getting these mythical steps that we're talking about.

00:17:50 ◼   ► So there's two ways to do that in iOS and WatchOS.

00:17:55 ◼   ► The first is Core Motion, which is the more raw direct motion API, and that provides concepts

00:18:01 ◼   ► of steps, distance, and floors if you have a device that has a barometer on it.

00:18:06 ◼   ► It also includes things like cadence and pace, but for my purposes, I don't really worry

00:18:10 ◼   ► about those.

00:18:12 ◼   ► And Core Motion is -- Core stores that data for the last seven days.

00:18:16 ◼   ► Though as I mentioned at the top of the show, as the data gets older, Core Motion's data

00:18:22 ◼   ► seems to somehow change and become unchangeable and trustworthy and becomes much more of a

00:18:27 ◼   ► scoundrel in terms of what it does and how it behaves.

00:18:31 ◼   ► And so it becomes unreliable the farther back in time you go, even as you -- it only stores

00:18:36 ◼   ► seven days, but if you ask for the steps from like six days ago, the number you get back

00:18:41 ◼   ► will be variant and changeable and day-to-day will give you different values, sometimes

00:18:45 ◼   ► go up, sometimes go down, even though nothing's happened, but this is what it does.

00:18:49 ◼   ► And as best I can tell, that is a feature, not a bug, based on conversations I've had.

00:18:56 ◼   ► But it also -- the thing that Core Motion has going for it is that it is essentially

00:19:00 ◼   ► real time, and you can even like observe -- you can set up like a long-running query that

00:19:04 ◼   ► says anytime the user takes a step, tell me.

00:19:07 ◼   ► And so if the user starts walking, and -- or this actually I hear from users a lot, is

00:19:14 ◼   ► the -- say you're trying to reach to your 10,000 steps, and you've taken 9,900 steps

00:19:20 ◼   ► right before bed, and you've realized this, and you're like, "Okay, I'm going to walk

00:19:22 ◼   ► 100 steps."

00:19:24 ◼   ► You want to sort of get confirmation that you've hit your goal before you go to sleep.

00:19:30 ◼   ► You don't want to wait around for that.

00:19:31 ◼   ► So you want to have it update roughly in real time.

00:19:33 ◼   ► And the only way to do that on iOS is with Core Motion, because the other version -- or

00:19:39 ◼   ► the other way you can get steps is from the health APIs and HealthKit, which is in many

00:19:45 ◼   ► ways you could say the like authoritative source on the device.

00:19:48 ◼   ► It is the grand repository where all health-related data goes to, you know, goes to be stored

00:19:54 ◼   ► forever.

00:19:55 ◼   ► It's lovely because it goes back forever, essentially, like from as long as the user

00:19:59 ◼   ► has maintained a iCloud backup and restore chain, or even now it syncs in iCloud, and

00:20:06 ◼   ► it goes back to whenever the data was collected.

00:20:09 ◼   ► But it is very slow to update.

00:20:12 ◼   ► On iOS 12, the steps typically don't show up there for at least 10 minutes, sometimes

00:20:17 ◼   ► 20 minutes.

00:20:20 ◼   ► But the only exception being if you are in an active workout on the watch, then steps,

00:20:26 ◼   ► samples are written to the HealthKit database roughly in real time, which sort of makes

00:20:31 ◼   ► sense, that in that mode it is kind of in more of a streaming system rather than an

00:20:35 ◼   ► aggregation system.

00:20:38 ◼   ► But that's kind of awkward because it can take up to 20 minutes.

00:20:41 ◼   ► Like it seems like it bundles step updates into 10-minute chunks, and then it writes

00:20:46 ◼   ► them 10 minutes after they were done.

00:20:48 ◼   ► So from the beginning of one of those chunks to when it gets actually written can be 10

00:20:52 ◼   ► -- can be 20 minutes.

00:20:53 ◼   ► So, CoreMotion, does that require permission to access?

00:21:11 ◼   ► Both CoreMotion and Health have permission and a certain sort of privacy request, things

00:21:18 ◼   ► in their place.

00:21:19 ◼   ► But I mean, who knows?

00:21:20 ◼   ► There are certainly issues.

00:21:21 ◼   ► I get the impression with a lot of this stuff that what you're saying, like there's things

00:21:24 ◼   ► beyond the use that I'm using them for that comes into play that is just -- you deal with.

00:21:31 ◼   ► But I mean, Health also -- another positive thing with Health, you can do observer queries

00:21:35 ◼   ► that run -- or like another scheme to get background time to get woken up that are actually

00:21:41 ◼   ► really clever because you can say, "Wake me up," whenever the user has taken a significant

00:21:45 ◼   ► number of steps, and it'll do that.

00:21:47 ◼   ► So whenever time your device is unlocked, which is actually another side point, Health

00:21:51 ◼   ► is only available when the device is unlocked.

00:21:53 ◼   ► CoreMotion is available at all times, so something you have to keep in mind, especially if the

00:21:59 ◼   ► -- or build something like a Today widget, which is visible when the device is unlocked

00:22:03 ◼   ► -- or is locked, but would not be able to access Health in that state.

00:22:09 ◼   ► So just all these kind of fun things you have to deal with.

00:22:14 ◼   ► And also another fun thing is that Health can take data from many sources.

00:22:19 ◼   ► So it could take data from your phone -- multiple phones, if you do iCloud syncing, including

00:22:25 ◼   ► phones that aren't yours, potentially.

00:22:27 ◼   ► So if you and your spouse share an iCloud account, and you turn on Health syncing, suddenly

00:22:31 ◼   ► Health contains steps from both of your devices combined.

00:22:35 ◼   ► It can also include devices such as Fitbits or other devices.

00:22:39 ◼   ► Users can manually enter Health steps into the HealthKit database.

00:22:44 ◼   ► It is great in that it pulls all this data together, but is problematic in that you don't

00:22:50 ◼   ► necessarily know how to get the data out of it.

00:22:52 ◼   ► So ultimately what I'm having to do is move towards Health because of the issues in CoreMotion.

00:22:57 ◼   ► It has the benefits of the data's always available, and the data just, you know, spends back in

00:23:03 ◼   ► time.

00:23:04 ◼   ► So previously there was an issue where if you didn't open Podometer++ for more than

00:23:06 ◼   ► a week, sometimes it would lose -- you'd have a gap in data because it would have kind of

00:23:11 ◼   ► fallen off the back of CoreMotion's queue.

00:23:14 ◼   ► With Health, that's never the case.

00:23:15 ◼   ► You can go back essentially until, you know, since the iPhone 5s was launched, which is

00:23:20 ◼   ► as far back as my Health's database goes with steps, I think, or until HealthKit was launched,

00:23:24 ◼   ► whichever came last.

00:23:26 ◼   ► It goes all the way back to there, and so I can do these great big imports, and it's

00:23:30 ◼   ► awesome.

00:23:31 ◼   ► But it has all these crazy issues with syncing, and more complicated, and what I'll get into

00:23:37 ◼   ► now, which is the real fun starts, is merging.

00:23:41 ◼   ► Merging and syncing.

00:23:42 ◼   ► I was worried, like, once you were saying, like, "Oh, it could take things from multiple

00:23:44 ◼   ► devices."

00:23:45 ◼   ► The first thing I thought of was, like, "Well, what if you're wearing a Fitbit at the same

00:23:48 ◼   ► time that you have your phone in your pocket, and they're both counting steps?"

00:23:53 ◼   ► Yes.

00:23:54 ◼   ► Or even just you have a watch and a phone.

00:23:57 ◼   ► Oh, man.

00:23:58 ◼   ► Like, it's a great situation that now, you know, a substantial proportion of my users

00:24:03 ◼   ► have, and they're both generating steps, and they're both generating step counts.

00:24:07 ◼   ► So, what is the correct value to show?

00:24:12 ◼   ► Right, because a lot of steps will be counted more than once.

00:24:15 ◼   ► Yes.

00:24:16 ◼   ► Well, I mean, sort of strictly, you would expect that if you put your phone in your

00:24:19 ◼   ► pocket and your watch is on your wrist and you're walking normally, they both should

00:24:23 ◼   ► be ideally counting roughly the same number of steps, which in some ways would be a great

00:24:28 ◼   ► and easy problem to deal with.

00:24:30 ◼   ► But say, for example, you're pushing a stroller with your hands.

00:24:34 ◼   ► Now, suddenly, your wrist is not really moving in a traditional way, swinging side to side.

00:24:41 ◼   ► So now, you are getting fewer steps with your watch, but your phone is still getting lots

00:24:46 ◼   ► of steps.

00:24:47 ◼   ► Oh, man.

00:24:48 ◼   ► Or alternatively, you could have a situation where your phone is, say, in your backpack

00:24:52 ◼   ► or in your purse, but your wrist is free.

00:24:55 ◼   ► So now, your watch is giving you lots of steps, but your phone is not.

00:24:59 ◼   ► It's still giving you some, not zero.

00:25:01 ◼   ► Giving you zero would make the whole problem super easy.

00:25:04 ◼   ► But giving you any number of steps is where it gets hard.

00:25:08 ◼   ► And the way that Health deals with this, so the Health database will show you a sort of

00:25:15 ◼   ► canonical number of steps.

00:25:17 ◼   ► And the way it does it is it has this vague sense of priority.

00:25:21 ◼   ► So most people don't know this, but in Health, you can go and set which devices you want

00:25:27 ◼   ► to be in what order.

00:25:29 ◼   ► And what it does is it looks, I think, in roughly 15-minute chunks.

00:25:35 ◼   ► It goes through and says, "Which device, in order on my priority list, has any steps,

00:25:41 ◼   ► any non-zero number?"

00:25:42 ◼   ► If it has a non-zero number, the first one it finds, that becomes the step count for

00:25:46 ◼   ► that 15-minute period, and it ignores the rest of them.

00:25:49 ◼   ► So if you have one step on your Apple Watch, and by default, Apple Watch takes priority

00:25:54 ◼   ► over iPhone, which makes sense.

00:25:56 ◼   ► But if your Apple Watch gives you one step, in the example of pushing a stroller, and

00:26:02 ◼   ► your phone gives you 500 steps, it'll give you one.

00:26:08 ◼   ► That doesn't seem like sophisticated enough logic.

00:26:12 ◼   ► Maybe not, but that seems to be what it does.

00:26:15 ◼   ► So what I did initially, with all this, and for the purpose of time, what I'll just say

00:26:19 ◼   ► is I do a Smart Merge, typically, where I look for, in each 15-minute chunk, which device,

00:26:25 ◼   ► only looking at Apple devices.

00:26:26 ◼   ► If you're running Fitbit or something else, I just ignore it.

00:26:29 ◼   ► For me, that would just hurt my head to deal with the way that other people state it.

00:26:32 ◼   ► At least I'll just look at Apple Watches and iPhones.

00:26:35 ◼   ► Whichever device gives you the most steps is the one that I looked at, which conceptually

00:26:40 ◼   ► means that I'm potentially over-counting, potentially, but at least I'm giving a more

00:26:44 ◼   ► representative case, and it means that I dynamically switch between devices based on which one

00:26:49 ◼   ► seems to be reflecting the most steps, which typically, "most" means best representative,

00:26:54 ◼   ► because apart from the issues with accuracy of measuring, if your watch says you took

00:27:00 ◼   ► 500 steps and your phone says you took 400 steps, you probably took 500 steps.

00:27:04 ◼   ► It's unlikely that it's over-counting in terms of what it's measuring.

00:27:08 ◼   ► That's exactly what I would do.

00:27:10 ◼   ► My solution to this problem would be exactly that, which is basically take whichever device

00:27:14 ◼   ► reported the most.

00:27:15 ◼   ► I feel like over-reporting is probably less common than under-reporting in all these different

00:27:19 ◼   ► situations.

00:27:20 ◼   ► Exactly.

00:27:21 ◼   ► And it's more honestly, for people, they want the number to be bigger.

00:27:24 ◼   ► It's not going to be sad.

00:27:27 ◼   ► Then they go to health, and the health number is going to be different.

00:27:32 ◼   ► And that'll drive people crazy, too.

00:27:34 ◼   ► And especially, there's all kinds of schemes.

00:27:36 ◼   ► I've had people who have health insurance things, where their health insurance is based

00:27:41 ◼   ► on a discount if they reach their step goal, say, and that number is the number that's

00:27:46 ◼   ► coming out of health, not the number that's coming out of pedometer++.

00:27:50 ◼   ► So they thought they were hitting their goal every day, but the health system is less than

00:27:54 ◼   ► that, and is under-counting, and then they're mad at me.

00:28:00 ◼   ► But the problem with the health system is it can go down, because if you don't sync

00:28:05 ◼   ► – say your Apple Watch is your priority device – it doesn't sync right away.

00:28:10 ◼   ► So it can think, then its number can start at 10,000 and then drop to 9,000.

00:28:15 ◼   ► If your Apple Watch comes in, it's the priority device.

00:28:18 ◼   ► It has fewer steps, and then the number can go down, and that drives people crazy, too.

00:28:22 ◼   ► You have to revoke their confetti.

00:28:24 ◼   ► Yeah, I have to revoke their confetti, or they get mad at me, and I'm running out

00:28:27 ◼   ► of time.

00:28:28 ◼   ► So understand that this is the nature of these kinds of problems.

00:28:35 ◼   ► There is no right answer, as you've seen.

00:28:37 ◼   ► And nothing is as simple as it seems.

00:28:39 ◼   ► No, nothing is as simple as it seems.

00:28:41 ◼   ► And it's actually, a brief aside, one of my early mentors in programming, I remember

00:28:46 ◼   ► specifically saying, "Never, ever use the words 'easy' or 'trivial' to describe

00:28:51 ◼   ► something in programming.

00:28:52 ◼   ► If you do, it is a clear sign that you have a fundamental misunderstanding of what programming

00:28:58 ◼   ► is.

00:28:59 ◼   ► Nothing is easy, nothing is trivial.

00:29:02 ◼   ► The strongest you could say is that something is relatively straightforward.

00:29:07 ◼   ► And if you don't have that perspective, you're either making assumptions that you

00:29:12 ◼   ► don't know about, or you're making assumptions that you do know about and are going to come

00:29:16 ◼   ► back to bite you.

00:29:17 ◼   ► And so don't call anything easy.

00:29:19 ◼   ► Step counting is hard, and there is no right answer.

00:29:22 ◼   ► So you just kind of do your best, sit in your thoughtful spot, and hope for the best.

00:29:27 ◼   ► That's fantastic.

00:29:28 ◼   ► Well, thanks for listening, everybody, and we'll talk to you next week.

00:29:32 ◼   ► Bye.

00:29:33 ◼   ► Bye.

00:29:33 ◼   ► [BLANK_AUDIO]