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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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:54
◼
►
Or even just you have a watch and a phone.
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: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: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: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: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: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:33
◼
►
[BLANK_AUDIO]