Transcript
[ Applause ]
>> Hello. Welcome to WWDC.
I'm Brad Jensen and today we're
going to be talking about What's
New in Location Technologies.
We've got three topics that
we're going to cover today.
First we're going to talk about
some miscellaneous API
improvements we've made.
After that we'll talk about our
big change this year, how we've
revised our authorization and
usage reporting story, and
throughout the presentation
we'll also touch on best
practices given the changes
we've made this year.
Now, a word of warning.
This presentation is geared
towards developers that are
already familiar with Core
Location, so if you're new to
our framework, we recommend you
check out our documentation
afterwards.
In addition, our session from
last year has a lot of helpful
advice for newcomers.
So let's get started.
For users of our geocoding API,
we have some exciting changes
for you.
We've added support for
interoperation with the Contacts
framework.
So you can now forward geocode a
CNPostalAddress.
And additionally, when you get a
CLPlacemark result, you can get
a CNPostalAddress from that
placemark.
Now, this is meant to be the
modern replacement for our old
support for the Address Book
framework.
In particular, you could geocode
an address dictionary and get an
address dictionary out of a
placemark.
On platforms where the Contacts
framework is available, we're
deprecating those address
dictionary API's.
However, on tvOS the Contacts
framework isn't available and so
you can continue to use those
address dictionary API's.
We're also adding support for
geocoding with a preferred
locale.
This won't impact which results
you get, only which language
they're returned to you in.
It's important to note that the
default behavior for Core
Location's geocoder has always
been to return results in the
user's preferred language.
If you specify a preferred
locale, you are overriding the
user's chosen language
preference.
That might sound bad, but there
are actually times when it makes
a lot of sense.
For example, if you're making a
travel guide up, you might want
to display text in your app that
matches the text the user would
see in the real world.
In that case you would want to
provide a preferred locale to
the geocoder that produces
results appropriate for the
region the user is visiting.
We've spent some time improving
our heading updates API as well.
Before we get to that, let's
just make sure we all understand
the jargon.
Heading refers to the direction
that you are facing, and course
is the direction you're actually
moving.
Now, with boats and planes you
tend to see a disconnect between
heading and course due to wind
or sea currents.
With cars, on the other hand,
you almost never see a
meaningful difference between
heading and course.
Even if there are very strong
winds that push the car to one
side or the other, the driver
will tend to compensate.
They don't want to get pushed
out of their lane, or even
worse, off the road.
This is a very convenient
observation because if we're
computing GPS estimates, we're
very likely to have a good
estimate of the device's course,
but sometimes computing the
heading can be a little bit more
tricky.
Even if we're able to accurately
estimate the heading of the
device, it might not be the
right heading.
For example, let's suppose the
user is navigating in their car
and they've mounted their iPhone
to their dashboard.
There's a very good chance that
they've angled their iPhone to
face themselves, but when they
do that, they introduce a
disconnect between the heading
of their car and the heading of
their iPhone, but when they're
navigating, they'd really like
to see the heading of their car.
Luckily, we just found a really
good way to estimate the heading
of the car.
We can use the course of the
iPhone.
So in iOS 11 Core Location will
now automatically detect
situations where heading and
course should probably be in
agreement and it will leverage
course information to provide a
more accurate heading update.
It's important to note that this
behavior is fully automatic and
always on when you use Core
Location's heading API.
So if you're creating an app for
planes or boats or augmented
reality, then you probably want
to use Core Motion's
CMDeviceMotion API instead.
Our detection logic is very
good, but it's not flawless.
There are times when it will
make the wrong call.
If you'd like to learn more
about their API, they had a
session this year.
I think it's definitely worth
checking out.
We've also spent a lot of time
improving our indoor positioning
system.
As you saw in the keynote, Maps
will now display floor plans for
many indoor venues throughout
the world.
At these venues any app that
requests best accuracy location
will automatically receive our
high accuracy indoor location
estimates.
We have four exciting
improvements that I want to
share with you today.
First, we've improved the
accuracy of our estimates.
Our estimates are GPS quality or
better.
Second, we've improved the
responsiveness of our indoor
positioning system.
When the user first enters a
venue, you'll start to receive
those indoor estimates much more
quickly than you did in iOS 10.
We've also improved how quickly
we detect floor transitions.
You'll get notified of the new
floor more quickly than you did
in iOS 10.
We've improved the availability.
And I don't just mean the number
of venues that Core Location
supports.
If the user wanders into a
region of the venue that maybe
hasn't been surveyed, you'll
still get quality indoor
estimates through Core Location.
We've improved the
interoperability of the indoor
positioning system with wireless
accessories.
So even if the user is, say,
streaming Beats 1 to their
AirPods, you'll still receive
quality indoor location
estimates.
For watchOS we're making our
continuous background location
API available.
You've probably already heard
about this API, but just in
case, this API allows your app
to receive location updates even
as it enters the background.
Now, in watchOS 3 it was
possible to get very similar
functionality using a
combination of Core Location and
HealthKit.
An HKWorkoutSession would allow
your app to continue receiving
location updates even if your
app was in the background.
However, we wanted to allow you
to create new location-based
experiences that weren't
necessarily workout related, and
so we're bringing our general
purpose continuous background
location API to watchOS.
Our usual guidance still
applies.
This is a fairly power expensive
API and so you should think
twice before using it, but if
you're creating, say, a
navigation app or a fitness app,
the continuous background
location is almost certainly
what you're looking for.
We wanted to ensure that this
functionality was exposed in
only one place, and so in
watchOS 4 HKWorkoutSessions no
longer give your app access to
location in the background.
Legacy apps will continue to
work, but when you link against
the watchOS 4 SDK, you must
adopt the continuous background
location API.
Otherwise, your app will be
unable to access the user's
location.
Luckily, it's very easy to adopt
our API.
There are simply three easy
steps.
First, you enable the
LocationUpdates background mode.
Simply navigate to the
Capabilities tab in Xcode,
scroll down to Background Modes,
and check the Location Updates
box.
Second, you need to set the
allowsBackgroundLocationUpdates
property to True on your
Location Manager.
We recommend you only do this
after the user has performed
some action which requires --
sorry.
Getting a little ahead of
myself.
We recommend you do this only
after the user has initiated the
workout session or the
navigation session.
That way you don't accidentally
start the continuous background
location session before you
meant to.
Finally, you simply call
startUpdatingLocation while your
app is in the foreground.
When your app enters the
background, Core Location will
keep your app running and
continue to deliver location
updates.
While we're talking about
workout apps, we have some
advice to help you create the
best possible experience for
your users.
First, we recommend you continue
to use HealthKit, even though
it's possible to create a
fitness app that doesn't use
HealthKit or HKWorkoutSession,
doing so will make your app miss
out on a lot of special tuning
we've put into Core Location for
workout scenarios.
So continue to use HealthKit and
HKWorkoutSession.
Second, if you know that your
user is in a pedestrian workout,
we recommend you use CMPedometer
to estimate how far the user has
traveled.
In some environments it can be
very tricky to accurately
estimate the user's location,
and if the user goes through a
run in one of those
environments, you'll find it's
even harder to accurately
estimate how far they have
traveled.
But if you know they're in a
pedestrian workout and you use
CMPedometer, your app won't be
affected by those difficulties.
Okay. That's the miscellaneous
topics.
Let's get to the big one;
authorization and use of
reporting.
We spent a lot of time iterating
on how Core Location's
authorization and usage
reporting works, and we've got
some exciting changes that we
think your users are going to
love.
First, let's quickly review how
it all works.
Core Location supports two
authorization modes; WhenInUse
and Always.
Always authorization allows your
app to access the user's
location anytime your app is
running.
Additionally, Always authorized
apps can use our background
monitoring API's.
These allow your app to get
runtime and receive information
when various location-based
events have occurred.
For example, the region
monitoring API will launch your
app whenever the user arrives at
or departs from a region of your
choosing.
The WhenInUse authorization mode
allows your app to access the
user's location anytime your app
is considered in use.
Usually if your app is in use,
that means it's in the
foreground, but that's not
always the case.
For example, if you're using the
continuous background location
API, on iOS Core Location will
draw a blue bar, a blue
double-height status bar at the
top of the screen, reminding the
user that the app is still
running and still accessing
their location, and in that way
your app is still considered in
use.
We introduced the WhenInUse
authorization mode because we
wanted to allow users a greater
level of control over how apps
access their private data.
And users love this.
They love knowing that apps can
only access their location at
times when they want it to.
And we think this represents a
great balance between the user's
ability to control how your app
accesses their location and your
ability to create compelling app
experiences for the user.
Since we introduced the
WhenInUse authorization mode the
response has been tremendous.
Almost 80 percent of
location-using apps on iOS
support WhenInUse authorization.
A mere 21 percent have chosen to
require Always authorization
from the user.
Users love the WhenInUse
authorization mode, and thanks
to your efforts, they almost
always have it available to
them.
We think this is fantastic, but
we wanted to see if we could do
better.
Now, let's look at some of the
reasons why an app might choose
to require Always authorization.
We think that one of the common
reasons is the developer's
simply confused.
It turns out that many apps
which require Always
authorization don't actually use
any of our background monitoring
API's.
It's very likely that these apps
would continue to function just
fine if they were granted
WhenInUse authorization instead.
But when the user encounters one
of these apps, they don't know
that.
They can't see the app source
code.
They don't know that it won't
monitor them all day and so they
have to treat it as though it
will, and this creates a very
poor user experience.
Now, a second reason we think
that many developers choose to
require Always authorization is
they're simply trying to give
their users the best possible
experience.
See, not all features can be
implemented reasonably with
WhenInUse authorization.
Some basically require Always
authorization, and we think that
these developers simply want to
ensure that their users have
access to all the best that
their app has to offer, but this
makes for a very poor user
experience for the users that
don't wish to grant the app
Always authorization.
They are forced to choose
between granting the app Always,
which is more than they would
like in this example, or
granting it Never, which means
they don't get to benefit from
any of the app's location-based
features.
And their final openings to
grant it Always and then revoke
that authorization after they're
done using the app.
In any case, the user is not
having a great time with this
app.
So for iOS 11 we're asking all
developers with Always
requesting apps to additionally
support the WhenInUse
authorization mode.
This change is both retroactive
and forward-looking, so when the
user updates to iOS 11, they
will be able to authorize any
app that requests Always
authorization the WhenInUse
authorization mode instead.
If you link against the iOS 11
SDK, you must provide a
WhenInUseUsageDescription.
Otherwise, your app will be
unable to request Always
authorization.
Furthermore, when your app
requests Always authorization,
we will additionally display an
option to grant your app
WhenInUse authorization instead.
With these new three option
prompts we have a new
UsageDescription string as well.
Your app needs to provide an
AlwaysAndWhenInUse
UsageDescription.
Since this is a different key
your app must provide it when
you link against the new iOS 11
SDK.
For apps linked against iOS 11
and later, Core Location will
not use the old NSLocationAlways
UsageDescription key.
So let's talk a little bit about
best practices; how does this
change things.
For apps that want Always
authorization we recommend you
provide all three keys, even
that NSLocationAlways
UsageDescription that I just
said we won't use.
And the reason why is if you
want to deploy your app on a
device that's running iOS 10 or
earlier, you need to provide
strings that it can understand,
and so you should continue to
provide that NSLocationAlways
UsageDescription.
Second, your AlwaysAndWhenInUse
UsageDescription should help the
user choose between Always and
WhenInUse.
We'll use it in context where
those are the two options
presented to the user.
So your description should
explain to the user what
features will be enabled if they
select WhenInUse authorization,
and then what additional
features they'll receive if they
choose to grant your app Always
authorization.
For all apps we recommend that
you only request authorization
when you really need it.
If you wait to request
authorization until the user has
performed some action which
requires access to the location,
then when the prompt appears,
the user will have all the
context, all this intuitive
understanding that they need in
order to understand why your app
wants access to location.
This makes it much more likely
that they'll actually grant your
app authorization.
For apps that request Always
authorization, there's a little
bit more to that.
We recommend you request
WhenInUse authorization first.
Requesting WhenInUse
authorization is a little bit
easier, not asking as much from
the user, but there's more to it
than that.
We think your app should make
WhenInUse its base experience,
the first thing users encounter.
Then, after the user has had a
chance to explore your app and
get to know all of its features,
when they discover that one that
requires Always, they'll try to
turn it on and at that point
your app can display a
transition prompt that requests
Always authorization on top of
the WhenInUse authorization you
already have.
When this prompt appears, the
user will once again have that
intuitive context they need in
order to understand why your app
is requesting Always and they'll
be much more likely to grant it
to you.
Let's see how that works.
So when the user first launches
your app, you'll have an
undetermined authorization
state.
From here you can request either
WhenInUse authorization or
Always authorization.
Let's see what happens if you
request WhenInUse authorization.
Core Location will display our
WhenInUse authorization prompt,
using your
WhenInUseUsageDescription in the
body of the alert.
Depending on the user's choice,
you'll end up with either
WhenInUse authorization or no
authorization at all.
After this point the user can
freely go to settings and adjust
your app's authorization value
to whatever they like.
But if the user has chosen to
grant your app WhenInUse
authorization, which they
probably will if you're
following our best practices,
you can additionally request
Always authorization.
When this happens, Core Location
will display a transition prompt
and will use that new
AlwaysAndWhenInUse
UsageDescription string.
From here the user can either
grant your app Always
authorization or keep it at its
current WhenInUse value.
After your app has requested
Always authorization it will be
unable to request any further
prompts.
So let's go back to the start.
What if you had requested Always
authorization at the very
beginning, right when your app
launches, for example.
The user will see this prompt.
They'll see a WhenInUse option,
they'll see an Always option,
and they'll see a Don't Allow
option.
If the user doesn't understand
why your app wants access to
location all the time, if they
don't have that context that
we're recommending you provide,
then it's very likely they'll
grant your app WhenInUse
authorization instead, and if
that happens, you won't be able
to initiate a transition prompt
afterwards.
Oh, and this prompt also uses
that new combined
UsageDescription key.
Okay. Before we move on from
authorization, I'm excited to
announce that on watchOS 4 Core
Location will support prompting
for authorization directly on
the watch itself.
Previously --
[ Applause ]
Previously, if you tried to
request authorization, watchOS
would alert the user that
there's a prompt waiting for
them on their phone and they
would have to go over to their
phone and respond to it there.
We haven't got this all finished
yet.
It's not in the seed you
received earlier this week, but
we do expect it to land in a
future seed.
When it's done, all you'll have
to do is rebuild your app and
the next time you install it,
you should start to see these
standalone prompts.
That's authorization.
Let's talk about usage
reporting.
But first, let's talk about how
it worked in iOS 10.
Core Location would report the
location usage of your app based
on which services you were
using.
Most services would result in
your app getting a solid arrow
in the status bar and in
Settings.
If you used the region
monitoring service, you would
instead get a hollow arrow.
And finally, if you were a
WhenInUse authorized app and you
requested the continuous
background location service, we
would draw this blue
double-height status bar that
I've mentioned a few times.
We felt this system was very
good.
It served us well for a long
time, but we thought there was
room for improvement.
This system over-represents the
privacy exposure of some of our
API's.
Let's compare two apps; one of
them using the significant
location change monitoring
service, and the other one using
our continuous background
location service.
Both of these apps will have a
solid arrow continuously.
However, the app using
significant location change
monitoring is going to receive
far less location information
than the app using continuous
background location.
The app using significant
location change monitoring is
only going to get updates when
the device has actually moved a
significant distance, and even
then, there's a rate limit on
top.
And so the app receiving
continuous background location
is going to get far more
location information, but they
have the exact same usage
reporting.
Furthermore, we thought that
Always authorized apps were
missing out on the blue bar as a
feature.
Suppose you have a navigation
app that is granted Always
authorization.
If the user is in a navigation
session, they probably want to
be able to return to that very
quickly after briefly using
another app, but in iOS 10
Always authorized apps don't get
this blue double-height status
bar.
We felt that these problems made
it difficult for users to
correctly interpret how apps
were using their location.
For example, let's consider
those two apps again; the
continuous background location
and the significant location
change monitoring app.
Suppose the user goes for a run
with the continuous background
location app.
They'll go on the run, they'll
come back, they'll see the solid
arrow the whole time, and when
they look at their map, they'll
see every twist and turn they
took.
When they install that app that
uses significant location change
monitoring, they'll see the same
thing, a solid arrow.
As far as the user is aware,
this app is probably receiving
the same amount of information
as their run tracking app.
So if users are misinterpreting
our signals, we decided the best
way to fix this was to adjust
how we indicate location usage.
We have a new policy and we
think you're going to like it.
We've changed how the arrow
works.
When your app requests location
information from Core Location,
we display a hollow arrow.
When you actually receive
location information, we'll
switch that to a solid arrow for
a few seconds.
We'll go through an example of
how that actually works in just
a few moments.
In addition, as you probably
guessed, we're bringing the blue
double-height status bar to
Always authorized apps that use
the continuous background
location service.
Now, we expect that this new
policy will help users
understand your app's location
usage more better.
So let's see.
Previously we had that hollow
arrow behavior and users came to
understand that the hollow arrow
indicated that an app was using
location in the background, but
it wasn't continuously receiving
updates.
It was receiving them
potentially intermittently or
only when specific events
occurred, and so they understood
that this arrow represented
low-powered background
monitoring.
We're now extending that
understanding to all of Core
Location's API's, and we think
this is much better for you as
the developers as well because
now users will be able to see
exactly how much, or as the case
may be, how little information
your app is actually receiving
when it's running in the
background.
If you're using our background
monitoring API's, you'll find
that you have a hollow arrow
more and a solid arrow less, and
we think this will help users
understand that your app is not
actually receiving every single
step, every twist and turn
throughout their day.
Okay. So let's look at how that
arrow works in practice.
Here we have a test iPhone and
it's currently at AT&T Park and
let's suppose an app is using
the Visit monitoring service.
The device has been stationary
here for a long time and so
we're displaying a hollow arrow
in the status bar because Core
Location is not delivering new
information to the app.
However, once the user gets up
and starts moving towards, let's
say the Ferry Building, Core
Location will detect that
departure event and alert the
app.
That will result in a solid
arrow appearing in the status
bar for a few seconds.
As the user continues their
journey the arrow will return to
its hollow state and it will
remain hollow until Core
Location detects an arrival
event.
After it detects that, it will
launch the app once again and
the app will receive a solid
arrow that will linger for a
couple of seconds, and then
after that it will remain hollow
until the user departs from that
location.
We really hope that this new
policy helps users better
understand exactly when and how
your apps are accessing their
location, and we think that it
will result in users no longer
blaming your app for things it's
not actually doing.
That's what we've got for today.
And just to recap, there are
three important points I want
you to remember.
First, users have more control
over how your app accesses their
location.
Specifically, users can now
grant your app WhenInUse
authorization if you request
Always authorization.
Now, we always recommend that
you communicate with the user
and help them understand why
your app wants access to
location, but apps that request
Always authorization have an
even greater responsibility.
If the user doesn't understand
why your app wants access to
Always authorization, then
they're not likely to grant it
to you.
They're likely to give you
WhenInUse authorization instead.
So you have that greater
responsibility if you want to
receive Always authorization.
And the best way we think that
you can communicate with the
user to help them understand why
you're asking for Always
authorization, the best way to
maximize your chances of
receiving Always authorization
from the user is to give them
that context that I talked about
earlier.
Give them that intuitive
understanding.
Let them explore your app with
WhenInUse authorization, and
then when they try to enable
that feature that requires
Always authorization, then you
initiate that transition prompt
and they will almost certainly
grant your app authorization at
that time.
Thank you for your time.
If you'd like to learn more, we
have some supplementary material
online.
We've updated our PotLoc app,
for example, so you'll find
that's got some new goodies for
you.
We also recommend you check out
these related sessions.
I've already mentioned the Core
Motion one, but the Privacy
session from earlier this week
was also very good and it has a
lot of great advice to help you
build an app that respects the
user's privacy.
Thank you for your time, and I
hope you enjoy the rest of WWDC.
[ Applause ]