WWDC2019 Session 705

Transcript

[ Music ]
>> Hello. [applause] Welcome to
What's New in Core Location.
My name is Adam Driscoll, and
I'm an engineer on the Core
Location team.
I'm excited to walk you through
the improvements we've made to
Core Location, new in iOS 13.
So, I think this is where we all
start out as developers.
We want to make our users happy,
and we have an app to do it.
And then, because you're here at
my talk today, I'm going to
assume that the user's location
is an important ingredient in
how your app can make your users
happy.
So, you'll want to use Core
Location.
Probably you already know that
your app will require the user's
permission to access their
location via Core Location, so
zooming in a little further,
you're going to need to request
and react to the user's choices
via our authorization prompting
system and then use the rest of
our API to do its thing.
Well, this is what we're here to
talk about today, because in iOS
13 our authorization system and
the options it presents has
changed, and so has our API in
the area of [inaudible].
Concretely then, we're going to
talk about always authorization,
which now works a little bit
differently,
WhenInUse Authorization which
can now do more,
Temporary Authorization, which
is brand new,
and we hope you and your user's
will love it.
And then I'm going to invite my
colleague, Andrea, up on stage
to walk you through the
applications of these things,
concretely, in the context of
beacon ranging.
All right.
Let's get started by looking at
that prompt I just used.
You may also recognize this from
the State of the Union talk.
In iOS 13, every new user
authorization interaction starts
with this prompt.
I do want to call out the option
we're not going to talk too much
about today, which is at the
bottom there, don't allow.
If the user selects don't allow,
then your app will not have
access to their location, and it
will not be able to prompt
again.
So, you're probably already
thinking this, but be mindful
about when you present this
prompt-- when you request for
this prompt to be presented to
your users.
Do it at a time when users will
best understand why you need
access to their location and be
most favorably disposed to
granting it.
Okay, but the agenda said we're
here to talk about always right
now, and there's no allow always
authorization option on this
prompt.
So, is it a mystery?
Well, if we look at how your app
would request the display of
this prompt, I think that
mystery will begin to unravel.
So, first up, you're going to
need a CL location manager, and
it needs to live for a little
while.
So, if you have a simple app,
setting it as an instance
variable on your application
delegate is a good place to put
it.
Then, your app would call one of
these two methods, either
request when in-use
authorization or request always
authorization.
For this walk-through, let's say
it requests always
authorization.
In iOS 12, this would result in
a prompt that actually provided
the user both options, both when
in use authorization and always
authorization, but now in iOS
13, it provides this one, which
does not have an option for
always.
However, Core Location remembers
what your app asked for, so if
you asked for always
authorization and the user
grants the most permanent
positive thing they can here,
which is allow while in use,
then that's what you'll get.
Apple will receive when in use
authorization, but it will also
enter what we call provisional
always authorization.
So, let's see how that will all
play out.
So, on the top of this timeline
here we have in blue what the
user will see and in green below
what your app will see.
Because under provisional
authorization, these two are
actually different.
So, your app asked for always
authorization, and then the user
granted it when in use.
Now, if the user goes to
settings, they'll see that your
app has when in use
authorization.
But, Core Location has called
your delegate back and told that
it received always
authorization.
So, we hope this will make it
really simple and obvious what
your app should do in this
context.
It should use it's always
powers.
It should whatever it needed
always authorization to do.
We'll get more into what that
might be later when we talk
about when in use authorization,
but for example, maybe it would
set up some GEO fences and then
start doing automation behavior
for the user in the background
based on their location.
Okay, if it does that, then Core
Location will monitor for those
GEO fences, and then at some
point the user will enter or
exit one of them, and an event
will be generated.
Normally, this event would be
delivered to your location
manager delegate, but because
your authorization is
provisional, instead, Core
Location holds onto it and waits
for a good time to ask the user
if they want to upgrade your app
to always authorization.
That prompt looks like this, and
finally we see a button at the
bottom that does allow always
authorization.
So your app has been thinking it
has always authorization all
this time, and the user has been
thinking that is has when in use
authorization.
This prompt is how we get
everybody back together all on
the same page in agreement.
Now, if this prompt were to
appear at a time when the user
does not understand why your app
needs access to their location
or they do not want your app to
have access to their location in
the background, then they can at
this point respond that they'd
like to keep your app in when in
use authorization.
But, if you and your users are
on the same page and they like
what they see, they can also
grant your app always
authorization from here.
Either way, the provisional
authorization period ends.
If your app ends up with always
authorization, then it will also
receive the event that started
this process.
If it ends up with when in use
authorization, it will not.
Okay, let's talk details.
So, first remember that while
your app is provisionally always
authorized, Core Location will
be monitoring for and generating
events that your app is
interested in but not delivering
them to your app unless doing so
would be consistent with the
when in use authorization it
actually has.
Second, the prompt that the user
can grant your app always
authorization from will occur
later.
And third, you can only start
this process once.
However, you can, as in this
example, request always
authorization right from the
beginning, or you can request
when in use authorization first
and then at some later point
when maybe the user interacts
with a feature of your app that
warrants it, seek always
authorization later as an
upgrade.
Okay, so Core Location is
monitoring and consuming events
that your app is interested in.
Let's talk about when they'll be
delivered to your app and when
they'll be dropped.
So first, as we've seen, they'll
be delivered if you app receives
always authorization ultimately
and not if it receives a when in
use authorization.
But they also won't be delivered
if the user just hasn't chosen
yet.
Now, Core Location waits for a
time when we think that the user
is not busy in order to maximize
their ability to understand
what's going on and minimize the
chance that they'll give a
get-out-of-my-way kind of
response.
So, during this time, if more
events are generated on that
basis, if you're monitoring
requests, then those events will
displace the ones that came
earlier, and the earlier ones
will be dropped.
And then finally Core Location
will drop the event part for
anything that's become just too
old.
That's because it may not be
relevant for your use case
anymore, but it also is
definitely not in the user's
perspective, in the user's mind
space anymore , so it doesn't
help them understand what's
going on.
So, finally, to be clear, I know
that this process will result in
dropped events at the beginning
for many use cases, but we think
it's really important for, but
please plan on this, because
you're just getting to know
users in this case, and by
pursuing always authorization,
you're asking for a lot of
trust.
All right.
I want to mention at this point
that the availability and
treatment of always
authorization varies by
platform.
So, tvOS only supports when in
use authorization, and watchOS
only really needs when in use
authorization.
That's because access to the
background runtime is very
tightly constrained on watchOS,
and most of our API does not
provide launching behavior.
Plus, context like the watch
face are effectively always in
use, so if you're working on a
complication, you're app
probably will not need always
authorization, but, probably
will not need always
authorization.
So, macOS similarly does not
support always authorization per
se, but prompting is automatic,
so you'll not have to request
authorization.
Which means that for iPad apps
on the Mac, when in use
authorization and always
authorization are effectively
equivalent.
Your UIKit code can and should
use whichever request, whichever
one makes sense from its
perspective on iOS when it's
running on the Mac.
All right.
So that's always authorization.
Now, we've already come up a
couple of times on this question
of what would your app need
always authorization for anyway.
Well, let's take a look at when
in use authorization and I think
we'll see.
So, I think I already, I
implied, but you probably
already guessed that if your app
asked for when in use
authorization, requests when in
use authorization up front and
the user granted it at this
prompt, then your app had
received when in use
authorization with no
provisional period and no
followup prompt.
And it would also have saved up
its opportunity to ask for
always later when maybe you
introduce a killer new feature
that really needs it.
So, how far can you go before
you have to start calling that
new feature killer and asking
for always authorization to
power it?
In iOS 12 and in early releases,
this table provided the answer
there.
As you can see, an app with when
in use authorization can receive
location updates, it can arrange
beacons, it can even receive
continuous location updates in
the background after starting
them in the foreground through
the use of the blue bar or pill
the background usage indicator.
But it could not start location
updates directly from the
background, and it could not use
any of our monitoring APIs,
which have the potential to
launch it in the background with
location-related information.
So what's a consistent feature
here?
Well, you'll notice that
services near the top of this
chart only function when your
app is in use.
While services near the bottom
function, have the potential to
deliver location related
information even when your app
is not in use.
So, in iOS 12, they're not
available to apps, which only
have authorization while they're
in use, but what if these
services at the bottom could run
in a mode where they don't
deliver related information to
your app unless it is in use?
In this case, they'd be
compatible with when in use
authorization, and we can stop
thinking so much about what
services your app is allowed to
use and start thinking more
about whether, just whether it's
in use or not.
So, that's what we've done in
iOS 13.
Each of these green checkmarks
now describes complete access to
all of our API including
significant location change
monitoring, region monitoring,
visit monitoring.
If your app is in use, it will
receive that significant
location change, that region
entry, that visit exit, and if
it's not, it will not.
So, under iOS 12, if you knew
your app needed to do region
monitoring, you might have
stopped thinking right there
about what kind of authorization
you needed.
But now, in iOS 13, you should
think a little deeper.
Whatever you need to do, will
the user know your doing it, can
the user be involved directly in
doing it?
In sort, when in use
authorization will be sufficient
for your app's needs if it will
or can be in use at the time.
Okay.
So, when is your app in use?
Well, at some point on this
timeline, your app will enter
the foreground, and from then,
until it enters the background,
it's considered in use, and then
actually for a few seconds more.
So this is the grace period
that's intended to cover your
app for race cases when the
event that you need location for
happens right before the user
leaves your app, but it's very
short, so try not to depend on
it too much.
Then your app will remain out of
use until it next enters the
foreground and this process
repeats.
Okay.
So, if you add location updates
to the list of background modes
that your app supports in Xcode,
then you can also get into this
situation where after your app
enters the foreground and
becomes in use, you start
updating your location, and then
you set the allows background
location updates property to
true on your location manager.
And then when you app enters the
background, that blue background
usage indicator will show, and
your app will continue to be in
use throughout its period in the
background until it enters the
foreground again.
Then, at some point you set
allows background location
updates to false, and that's
sufficient to return to the
usual behavior where the next
time your app leaves the
foreground, it will cease to be
in use.
All right.
What about complications?
Well, the complications on the
current watch face are
effectively always in use.
Note though that like the grace
period in the background usage
indicator period, this is a dark
green color, and your app is not
considered in use enough to
request an authorization prompt
in this state or to do anything
but receive location updates.
So, if you're working on a
complication, your app probably
will not require always
authorization, but you will need
to seek authorization from your
app context.
There's one other case I'd like
to draw your attention to
because it provides a lot of
additional power to when in use
authorization in those cases
where you can afford to directly
involve the user.
So, if you can do that, then you
can create a local notification
with a UN location notification
trigger that names a region of
interest.
Then, when the user enters that
region, that notification will
become relevant and will be
displayed to them.
Note that at this point up to
this point your app has not
received any information about
where the location, where the
user is, and you're not told
when this notification presents
or doesn't present.
However, at this point, if the
user taps through from that
notification and launches your
app, boom, your app is in the
foreground.
It's in use in the regular way,
right at the context where you
needed it to be.
Okay, so remember, all the Core
Location API surfaces are now
available to all clients under
at least some circumstances, and
you can use local notifications
or the blue background usage
indicator to get or stay in
those circumstances as
appropriate, which means you
should now need always
authorization only for those
cases, those kinds of automation
where the user can't or doesn't
want to be involved before your
app is.
We hope that this will help you
make your authorization story
more comfortable for all those
users in other cases.
Okay, and there's one more way
in which we've made a temporary
authorization, when in use
authorization cooler, and that's
that we allowed it to be
temporary.
So, that's what the middle
button on this prompt does.
Let's take a look at all the
states that your authorization
states that your app can be in
and some of the transitions that
you can make between the VR
prompting system so that we can
figure out where this temporary
authorization fits into the
picture.
So, starting with the way this
works in iOS 12, when your app
first enters to foreground, its
state is not determined, which
means that it does not have
access-- by the way we're going
to have more permanent states
off to the sides and more highly
authorized states up to the top.
So not determined is at the
bottom.
Your app cannot access location,
the user's location, but it's
not denied.
It's not determined.
So, crucially, in a not
determined state, your app can
request an authorization prompt,
and as soon as it does, then it
may be denied, and then it will
not be able to prompt again, but
the user could also grant a when
in use authorization, and if you
request always authorization
from there, you can get into
always authorization, or you can
ask directly for always
authorization from the
beginning.
So, that's iOS 12.
Now, in iOS 13, we've seen that
the path to always authorization
involves a new temporary state
called provisional always
authorization, which functions a
lot like always authorization
but from which a transition back
to when in use authorization is
also possible.
Well, a temporary authorization
works very similarly.
It's a temporary state that
behaves a lot like when in use
authorization but from which a
return to not determined state
always happens as soon as your
app is no longer in use.
Okay, so temporary, a when in
use authorization is temporary,
but otherwise it works just like
when in use authorization.
So, your location manager's
delegate will be called back
with location manager did change
authorization to authorize when
in use and then again later with
not determined.
But the key is, after that
happens, your app can and should
request authorization again the
next time it needs it.
And the main thing to remember
is just that authorization with
temporary when in use
authorization is closely tied to
when exactly your app is in use,
and also because you can request
it again, it's more closely tied
to where in your app's flow you
actually need location access.
So, let's look at some of those
green in usage charts again now
in this light.
So here's the most basic case,
but we'll make it even more
basic by pulling that second
region of usage up close to the
first one.
Now, while your app is
foreground and in use, let's say
the user interacts in a way that
makes you know that your app
will need authorization,
so you request authorization at
that point.
And the user grants it-- with
the allow once, the user grants
a temporary when in use
authorization.
In that case, your app will have
when in use authorization
through the remainder of that
foreground period, across that
brief dip into the background,
and then through the next
foreground period all the way
until it fully enters the
background at the end.
All right, but what happens if
that gap in the middle opens up
a little bit more and your app
really ceases to be in use in
between.
Then, the user does that thing,
you request authorization, you
receive a temporary when in use
authorization, but it's going to
lapse when you enter into the
background.
So, you're probably thinking,
okay, when do I ask for
authorization again in that
second period of in useness?
Should I do it as soon as I
enter the foreground?
No, you shouldn't.
You should instead keep in mind
what it was that caused you to
ask for authorization in the
first place.
For example, maybe the user
asked that you keep a MAT view
updated with their current
location or that you GEO tag a
message they're sending.
If they do that again in the
second usage period, then ask
for authorization to do it in
order to support them with that
request.
If they don't, don't.
The key is, if the user doesn't
expect you to continue using
their location from the previous
time, don't ask again as soon as
you enter the foreground.
Okay.
But, sometimes maybe you're
tracking a user's run or helping
them navigate, and the user will
expect you to continue accessing
their location even after across
periods of time in the
background.
Well, in that case we're
probably in this situation
whereas after you start that run
and you ask for authorization to
record it, and you receive
temporary when in use
authorization, you're going to
be starting location updates.
You're going to be setting
allows back on location updates
to true.
And so when your app enters the
background, that blue background
usage indicator will show, and
your app will remain in use and
therefore continue to have its
temporary when in use
authorization uninterrupted
across that background session.
Then, when [inaudible] in the
foreground again, end the run or
end the navigation session, you
set allows background location
updates to false again, and we
return to the normal situation.
Okay, I do want to call out that
there is a valid use case for
requesting authorization more or
less as soon as you enter the
foreground, which is if the user
expects your app to always have
authorization, always be
updating a map with their
location, but only when they're
directly interacting with it.
In those cases, when you enter
the foreground, request
authorization, but don't set
allows background location
updates then you won't get the
background usage indicator, and
your authorization will just
lapse when you enter the
background.
Then when you come to the
foreground again, repeat.
Now, ask yourself seriously
though, if the user really wants
you to do this.
Maybe they do.
In such cases, you're likely to
end up in more permanent when in
use authorization sooner or
later, but it makes sense to
still ask in this way for that
period of time before users are
sure if they want to grant that
or not.
Okay, so we've seen that when in
use authorization can now handle
some uses such as region
monitoring and that temporary
authorization can bring them
that power even on a
case-by-case basis, and I
promised you some revamped
beacon ranging API.
So I'd like to invite my
colleague, Andre Guzzo, up on
stage to walk you through that.
Andre.
[ Applause ]
>> Hi everybody.
My name is Andre Guzzo.
I'm a software engineer in the
Core Location team, and I'm here
today to talk to you about
beacon ranging.
We'll see what's changed in the
API in iOS 13 and I will walk
you through a simple example on
how to use beacon ranging and
provide a great location
experience to your users without
the need of always
authorization.
Let's start with a refresher
about beacon ranging.
What is beacon ranging?
We introduced it in iOS 7 as an
extension of the regional
monitoring API and as a way to
provide a new dimension of
location aware experience to
your users.
It's part of the region
monitoring API because you want
to use region monitoring in
order to initiate ranging.
You want to assure you are in an
area where your beacons are
visible before you start ranging
for them to not waste resources.
And region monitoring since its
introduction has required always
authorization.
Now in iOS 13, it can be used
with when in use authorization
instead.
So, as I said, we introduced
beacon ranging as an extension
of region monitoring.
So in order to represent a
region which is defined by the
presence of beacons, we have
extended the CL region object
into the CL beacon region, and
among other properties, we
included what actually
identifies a beacon, which is
[inaudible] major and minor.
And you would pass this data
type to the beacon ranging API
in iOS 12 and previous releases.
But let's focus on this
[inaudible] it identifies
exactly one beacon.
Well, you might configure the
same [inaudible] on multiple
beacons, but it would appear
like a bigger beacon.
So, when I'm defining a region
with all the elements of the
[inaudible], I'm actually
defining a region with exactly
that beacon matching the
[inaudible].
But in the beacon region case,
we can omit the minor and major
number, which is equivalent to
using a wild card.
So, I can omit the minor number,
and now my region is defined by
all the beacons sharing the same
UUID and major number.
In the same way, I can omit the
major, and now I extended my
region to include all the
beacons that have just the same
UUID but different major and
minor numbers.
This is why in iOS 13 we
introduced a data type CL Beacon
Identity Constraint, in order to
represent the meaning of
[inaudible], which is telling me
what are the beacons I'm
interested into and that are
defining my region.
And now, you will use this
identity constraint, this data
type, when you create your
beacon region.
And you can later get an
instance of this data type when
you will need it to access the
new beacon ranging API where
this data type is expected.
So, let's now see how this works
in practice by making a simple
example.
Imagine we are building an
application to be used while
visiting a museum.
We want to provide the visitor
with details about the object
he's standing in front of
without the need of having him
typing in some long name or
browsing through the catalogue.
To achieve this, we are going to
install our beacons in the
museum in the exhibition rooms.
We will use the same UUID for
all the beacons that we will
deploy in our museum.
We will configure a specific
major number for each of the
exhibition rooms and a minor
number for the specific object
inside the room.
Then, we need to be able to
determine when the visitor is or
not in one of the exhibition
rooms.
We don't want to be ranging
while the visitor is in the
cafeteria doing something else.
We want to be ranging for
beacons when we know he is one
of the exhibition room and
engaged with the visit.
At that point, we need to
determine what is the object
closest to the visitor and
provide details about that one.
Finally, all this happens while
our application is in use.
We can safely assume that since
it's a guide for the visit to
the museum, the visitor will
probably be already engaged with
our app, but if we want to
remind the visitor about our
application, we can use a local
notification to trigger a
notification when the visitor
arrives physically to the
museum, so he has a choice to
tap through and start our
application.
So, let's see what our app would
look like.
This diagram represents the
state of our application while
it's being used.
We will be monitoring for our
beacon defined region and react
to enter and exit events, and
while we are ranging, we will
receive updates about the
proximity of our beacons.
Let's focus on the first state,
so how do we define our
beacon-defined region.
As I said, we are going to
install beacons in all the
exhibition rooms, and we will
use the same UUID for all the
beacons and then major for the
exhibition room and minor for
the specific object.
Since we are interested in
determining when the visitor
enters any of our exhibition
rooms, we will omit major and
minor, and we will just provide
the UUID when creating our
beacon region.
Let's see how this looks into
code.
First of all, we are going to
ensure we have when in use
authorization.
Then we will create our beacon
constraint by providing only the
UUID.
Then we create our beacon region
with a new API by providing the
constraint as argument, and we
can start monitoring for it.
At this point, we are able to
determine when the visitor is
inside or outside one of our
exhibition rooms.
And so we just need to react to
the state change.
We have to start ranging when
the visitor enters one of the
exhibition rooms and stop
ranging when he leaves one of
the exhibition rooms.
We achieve this by defining our
delegate method, and in the
delegate method, we will react
accordingly to the state.
If we are inside, we will start
ranging.
If we outside, we will stop
ranging.
And as you see we are providing
the beacon identity constraint
we just introduced that you can
retrieve through the region.
Note that this delegate method
will be called, also the first
time you start monitoring, in
order for you to know your
initial state, so if the visitor
starts your application while
he's already in one of the
exhibition rooms, you will have
your delegate being called with
the state inside.
So, you will be aware about
that.
Okay, now that we know how to
react to entrance and exits from
the exhibition rooms, let's see
what we have to do when we are
inside in order to determine
what the object closest to the
visitor.
We want to provide information
about what the visitor is
actually standing in front of,
and we want to know if the
visitor moves inside the
exhibition room what is the new
object closest to him.
We only need to define our
delegate method.
It will be periodically called
with a status update on the
proximity of your beacons, and
you will receive a list of
beacons already categorized by
proximity.
So, it's very easy to know which
one is the closest beacon and
act accordingly.
So we have seen what do we need
to do while our app is being
used, but as I said, we might
want to engage the visitor when
he arrives to the museum.
Most likely, they downloaded our
application the day before or a
few days earlier.
So we might want to remind him
to launch our application while
he is inside the museum.
We are going to use user local
notification for that, which is
triggered by the location.
So, we will need to create an
actual geographical region by
providing the geographical
coordinates of our museum.
Then, I actually declare that
I'm interested only in arrivals.
You might want to register your
notification also for departures
if you want to take any action
in that case.
And then we use the user
notification API to register our
local notification.
Okay, so this is all.
We had a brief refresher about
what is beacon ranging.
We have seen what change in iOS
13 in the beacon ranging API and
a simple example on how to
provide a great location aware
experience by using beacon
ranging only when in use
authorization.
And now, back to my colleague,
Adam, for a final summary.
[ Applause ]
>> Thanks Andre.
So, what are the three things
that we need to think about?
First is location authorization
has changed.
It works in some new ways.
We hope that it will actually
really fit your app better and
help you to increase the
confidence that users have in
interacting with your app by
letting them know that their
privacy is being carefully
guarded.
That means there is a call to
action here to test, test your
app.
Try living on it with granting
only temporary authorization,
temporary when in use
authorization.
Does it work?
Is it irritating?
What could you do to improve
this experience for your users
so that they don't have to
decide to grant or deny your app
permanent authorization to
access their location before
they're ready?
And then, in the spirit of
testing, ranging has a new way
to help make you, help you make
location-related experiences
that are really great, and we
have a sample in the toolkit
today, which is really great for
the new ranging, exploring the
new ranging APIs.
Very minimal, just what you need
to know.
So, if you have questions, we
have two labs this week.
One is in an hour or something.
I don't know what time it is.
There's 11:00 to 1:00 today, and
the other one is 1:00 to 3:00
tomorrow.
And you've already about
temporary authorization in the
keynote, and in the state of the
union, and now this is the third
time, so if you'd like to hear
it a fourth time, they're going
to cover it in designing for
privacy today at 2:00.
There's also, in the rest of the
week, a couple of mapping
related talks, both indoor and
outdoor that pair really well
with Core Location, but they
don't fit on this slide.
So, the most important thing is,
enjoy your time here the rest of
the week in WWDC19, and we look
forward to seeing you in the
labs.
[ Applause ]