Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
[ Applause ]
>> Jay Bruins: My
name is Jay Bruins
and I'm a Core Location Engineer
and I'm here today to share
with you some exciting new
changes that we've made
to the Core Location APIs and
so let's get right into it.
We've got a number of things
we're going to cover today.
The first thing that we're going
to cover is changes related
to the new Multitasking
Behaviors.
And so some of the multitasking
behaviors change the way
location work and so we're
going to cover those today.
The next thing I want
to dive into is going
to be Creating Fitness
Applications.
Many of you guys already have
applications in the store
that allow a user to track
their fitness but, with a couple
of changes you can actually
get much better battery life.
And lastly, we've got some
exciting new region monitoring
changes today that I'm
happy to share with you.
I'd like to start by
saying this is not a review.
If you're watching this
online you might want to pause
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and go back to last year's
video, which is going
to be much more basic.
This review-- today I'm
going to move very quickly.
So, if you're in the
audience stick around.
You're going to experience
our exciting new features
but you might want to kind of
review our documents online
to get yourself grounded a bit
better before diving into Code.
So with that, let's
start talking
about the Multitasking
changes and how they relate
to your location application.
So, one thing to keep in mind
with the new multitasking UPIs
is that we've allowed the user
to take control over
multitasking behavior on iOS.
So, with that the user can
actually disable multitasking
across the device.
Similarly they can single
out your application to say
that I don't want it to be
running in the background.
Usually it's to save
power or some sort
of conception issue like that.
And lastly, they can temporarily
override multitasking
by quitting your app
from the app switcher.
And if they do this,
this is a signal to us
that they're not really
interested in the features
that your application
provide for a period of time
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and they'll manually
launch their application
when their interested
in receiving your
functionality again.
So, with that let's talk
about the Core Location APIs
that are affected by this
multitasking ability.
Specifically, continuous
background location.
So, if you're a fitness
application
or you're providing turn-by-turn
directions and you want
to continue running the
background with the power
on we're-- this is going to
be affected by the switch.
Similarly, if you're using
significant location change
to provide overall
day-to-day tracking of the user
or if you're using fences to
provide notifications of arrival
or departure, these
APIs are disabled
in the even the user
turns off Multitasking
for your application.
So, we have a couple of
recommendations for you
and these really dovetail
with the recommendations we've
always been providing you
with regards to authorization
on the app.
Be clear about why
you're using Location.
These goes beyond just
specifying NS Location usage
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
description key inside
of your infoplist.
What we'd actually like you to
do is use location in response
to users interaction
with your application.
Start location when the user
presses the location button
or does a search and they
need to know where they are.
Be selective about
using location.
If you turn off location
and the user sees
that you're responsibly
turning off, they're more likely
to trust you with their
location and they're more likely
to leave Multitasking enabled.
Similarly don't start
on every launch.
Realize that your application
can launch for a number
of reasons, including
into the background.
And so if you're
launching location,
if you're starting location
every time you're running,
you're just going to guarantee
that you drain the
user's battery.
And if we're talking about
launching our app proactively
to do fetches in order
to have a fresh UI,
we're going to be throttling
you more aggressively,
if you're using location.
But that's not to say
that you shouldn't do it.
It's just that you need to be
cognizant of these changes.
And especially when you're
fetching proactively understand
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the location that
you're going to achieve
for the user might
not actually go
to a user's specific experience
because the user might
choose not to launch you.
And so with it, turn off as
appropriate in the background.
If you have a location
that's good enough
to hit your server query
or a certain amount
of time has passed and you're
just not going to get a kind
of quality location because
the user is in a bad location,
then turning off location
will really allow you
to save battery,
prevent being throttled
and overall have the best
user experience possible.
With that we actually
made some changes
to continuous location
behavior in order
to help you avoid
killing battery.
So, to remind you this API is
what you get when you specify
that you want to be a
Location background app.
And if you put this
in your infoplist
when you start location
we will keep--
we keep the device awake as long
as you can tune in
to use location.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
But in iOS 7 because of these
extra launching tasks we
actually don't want to
start in the background.
We see Continuous Location as
an extension of the foreground.
So, a user starts
navigating to a location
and then they suspend their
application and they lock it
and they put it on
their dashboard.
Turn by turn should continue
but you shouldn't start
in the background.
Similarly if they go for a
run you know the user had an
opportunity to start your
app before they switched
to their music player.
So, starting in the
foreground is not
that stringent of a requirement.
We realize that there are
a handful of applications
that are trying to do day-to-day
tracking using significant
location change.
And for those applications we
will still honor the background
modes key and keep
the device awake
when you are using location.
But in general, if
you start Location
in the background
we'll simply leave--
we'll give you location services
as long as these are running,
but we won't guarantee
that we'll keep you running
and this is the best tradeoff
for power and user satisfaction.
With these changes
however, it's possible
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the user could
tell you that hey,
I'd like to get directions
to dinner and tell us,
I don't want any
applications to do multitasking.
And so, in that situation
it would be a good idea
to check a new property on
the UIApplication instance,
backgroundRefreshStatus.
If your status is currently
available then APIs will behave
exactly as expected.
However, if it's denied this
means that the user has chosen
that they don't want
your application
to be running right
now or running
in the background I should say.
So, as a result we won't launch
you and we won't allow you
to continue running
indefinitely.
There's-- and if this happens
and you have specific indication
from the user that
you actually--
they do want your app to
function it might be a good idea
to pop a dialog and tell
them to go to settings
and correct their situation
so that they can get
the app functionality
that you want, that they want.
Now, there's one other option
and this is restricted.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And this is if parental controls
or an enterprise
profile were installed
and Multitasking is locked off.
In this case, there's not really
much point in telling the user
to go to Settings
because there's nothing
that they're going to be able
to do inside of Settings.
So, instead please have your
application degrade gracefully,
gray-out some menu options
or just hide them completely
and don't tell them that hey,
there's these great features
that your phone can't do because
your system administrator locked
it out.
Lastly, if you're running into
the background at the point
that a change occurs we'll give
you a notification of this fact
and you can check this.
Now that's one caveat
and that is
that this API is actually not
available in the first seed.
So, the second seed
which is going
to be available shortly will
actually have this API in it
and that will allow you to
start tuning your applications
to provide the best
user experience.
With that, let's talk about
creating a fitness application.
As many of you already know
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
because we've gotten many
great examples in the store,
creating a fitness
application is easy.
Start-- allocate a
locationManager, set yourself
as the delegate,
specify the fact
that you're a fitness
application.
Now this is a step that
not everyone is doing
and I would highly
encourage you to do
so because it tunes the
way that auto pause works.
So, if your user is
running around a track
and it looks overall at a high
level view like they're moving
about 100 yards, stopping and
moving about another 100 yards,
now this is in an oval.
But if you're in a car
that's not a lot of movement
and so we'll assume that if
you were navigating in a car
that actually the user would
rather pause their activity
right now because navigation
is not really relevant anymore.
But if you're in a
fitness application,
clearly the user
is still running
and we should keep going.
Similarly if you specify
fitness activityType.
When we're considering
mat matching scenarios,
we're far more likely to leave
you meandering around a park
and less likely to snap you
to a freeway if you tell us
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that you're a fitness
application.
So, doing this will help
tune Core Locations behavior
to maximize your fitness
application's quality.
And, of course, the most
important step start
location updates.
At this point you've got an
application that's happily
collecting a location and
its going about its business
and your user is
usually pretty happy.
But it's also starting
to actively drain the
user's battery life.
To understand why, let's look at
how GPS works on an iOS device.
So, inside any iPhone
or any device that's got a GPS
chip there's actually a specific
chip that's sole purpose is to
decode signals from a satellite
and encode them as locations
and deliver them to the device
at which point we
can deliver them
to you via the Core
Location APIs.
And this is an ongoing process
that occurs whenever
you've turned on GPS
and it consumes a
certain amount of battery.
Beyond just the battery that's
consumed by the chip itself,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the phone stays awake.
So, if we had a way
to turn off the device
and let it sleep while the
GPS was continuing to function
and coalescing updates
into a single--
coalescing updates on
that chip then we can end
up leaving the device asleep.
And now if the user pulled
the device off their arm
and they wanted to check the
status of their run and woke
up the phone, we could deliver
all of the location updates
in one deferred updates to you.
And it turns out that
if we leave the phone of
but leave the GPS on that
roughly equates to up
to 40 percent power savings.
So, that's basically the
difference between going
for an all day hike and having
a completely dead battery
or getting back to the
trail head and being able
to call your family member
and ask for a ride home.
So, this is really exciting.
To come with an API that would
work and allow us to defer
as maximally as possible,
first we had to come
up with what an idealized
fitness application looks like.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so for us, and we model this
basically off of apps that are
in the app store and usually the
script goes something like this.
User turns on their phone,
starts running applications.
You give some sort
of notification being
like hey, I've started the run.
And now this is where
we'd actually
like the phone to go off.
And so we realize that some
users like to be motivated
as they're running so that
at some point later there--
they've gone a certain
amount of distance.
It would be nice if the
phone could wake up,
know that they've gone a mile
and say congratulations
you've made a six minute mile.
Keep up the good work!
And again, going back to sleep
and similarly sometime
later say,
hey look you have
45 minutes remaining
in your workout, keep it up.
And then do this a
couple more times
and eventually know
work out's completed.
You've gone 9.6 miles, awesome.
So, if we could do this
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and if we could defer location
updates during this period then
we can actually save a
significant amount of power.
And so, to achieve this we left
the API more or less alone.
You set up your fitness
application just
as you did before.
The magic is going to come
in from how you handle
locations from us.
So, if you receive an
array of locations inside
of the DidUpdate
Locations Delegate Method
when you update your model
with your run information
this is the model
that you guys have written
that's going to keep track
of how fast they're
running, how far they've run
and be able to plot it on a map.
Do this step as you've
done before,
but now if you're not currently
deferring location updates go
ahead and query that
model to figure
out how much further you
have until the next goal
for that user the next time
you want to motivate them.
And similarly you might have
a time-based motivation.
So, let's say you've got a
date that's you're next audible
that you want to give
and you compute how far
in the future it is.
Now if you tell your
locationManager
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that I'm allowing you to
defer location updates
until the user has
made it this far
or this amount of time has past.
This is the clue to us that
we can sleep the device
if possible to save power.
And the last thing you need to
do is keep track of the fact
that you're deferringUpdates
because this is useful
for your application to know.
When your event finishes,
when the users reach their goal
we'll send you a notification
to a new delegate method
DidFinishDeferred updates
with error.
And in the normal case
this is not a problem.
We just have to mark the fact
that deferred updates are
completed and will rearmor logic
for the next time so that
the next goal can fire,
the next goal can be
scheduled and fire.
Now, of course, there's
a handful of errors
that we could return to
you in this situation.
And so I'd like to take
an opportunity now to go
over a couple of those reviews
to help give you a
better understanding
of how this API is
working under the hood.
So, the first error
that you could run
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
into is NotUpdatingLocation.
Needless to say its impossible
for us to defer location updates
if there are no location
updates.
So, please remember
to startUpdatingLocations
before you defer them.
Similarly, if you don't
specify that you would
like to use a GPS, if you're
using a much less accurate
request for location, we don't
have a GPS chip that's going
to be running and so we have no
way to offload location to it.
Quite frankly there's
a good chance
that if you're not using GPS
that you're already saving a
significant amount of power.
So, this is a GPS technology.
So, to put your desired accuracy
back to the default value
and just leave it alone in the
first place and specify best.
And lastly it's possible that
you've told us that you'd
like to filter locations via
the DistanceFilter property.
And quite frankly us
collecting a significant number
of locations and then
deliver it you all at once.
If you're not interested in most
of them is it really beneficial.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, to use this API
you need to specify
that you don't want
a distance filter
or just leave again
the default value.
So, these three errors once
you've established your
application really
shouldn't ever crop up again.
If they do, it's pretty
much a programming error.
Normally, we would like
to assert in the case
that you've got a
programming error
so that we call your attention
to it as fast as possible.
But because these
properties already existed
and it's possible that your
code's already using them,
we didn't want new assertions
to pop up in your code.
So, inside of your
UpdatesDidFinish,
the DeferredUpdatesDidFinish
delegate callback consider
throwing your own assertion
so you can call your
own attention to it.
That way when debug builds
you can iron out these issues
and your users will never see it
and we can maximize
battery life.
Now an error that you
actually can get that's normal
is DeferredCanceled.
This simply means that you
disallowed deferred updates
and if this happens while we're
currently updating we give you a
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
callback saying hey we're done
because you told us we're done.
But it's also possible to
get a cancellation event
if you reschedule deferred
updates with new parameters.
And the reason why is
because this is a fully
asynchronous API.
So, if you're attempting
to tell us hey, go ahead
and change the parameters
by how far I want to run,
at the same time we're trying
to tell you, by the way,
you're previous criteria
was hit.
Now you have an impossible
situation
where you can't know whether
or not we're telling you hey,
you finished the new one or
you finished the old one.
And so to resolve this issue,
you will get exactly one
callback for every call
to allow
DeferredLocationUpdates.
So, if you're already deferring
and you call either disallow
or allow you will get
a cancellation event.
And again assuming
that we're not already
in flight telling you that
you hit your exit criteria.
So, if you look back
at the sample
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that I provided earlier this
is why we're keeping track
of whether or not we're
deferring location updates.
Because if you're not doing this
and you're constantly
rescheduling us you're getting
spurious cancellation errors.
And worse than that you're
causing us to recompute
when the device is
allowed to sleep,
which basically is just going
to keep pushing that date
out into the future and
there's no guarantee
that we'll ever sleep
and there's no guarantee
you'll ever get power savings.
So, keep track of whether or
not you're deferring updates
and know that cancellations
can occur
because you've told us
to change something.
Another error that you
can run into is kind
of a general catch-all error.
It's specifically saying
that DeferredUpdates failed.
Now the easiest way for you
to get this error is simply
because you're trying to
defer updates on a platform
that doesn't support this.
So, if you don't have a GPS,
for example, there's no way
that we could possibly defer
updates to the GPS chip.
Before starting DeferredUpdates
if you check to see whether
or not it's available this will
save you again spurious errors.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This can actually happen
under real circumstances.
Consider the case where
GPS simply isn't available.
Usually this can happen
if you start a run
inside your apartment
and you haven't made it back
down to the ground
floor to go outside.
The GPS simply isn't ready yet.
It's not fixing so if you
try to tell us let me know
when the user's gone a mile,
and we don't have
a solid start point
that we can agree upon
then we can't tell you
when the user's gone a mile.
So, we'll go ahead and
give you a deferred error.
Similarly along the course
of their run you can
have a minor hiccup
that stops location updates.
This could be moving
through a tunnel
or any other temporary problem.
And so in either of these
situations the simplest thing
to do is simply to retry
the next time we give you a
location update.
Because if we can compute a new
location update there's a good
chance that we've
already solved the problem
that caused this issue and so
it's a good time to reschedule.
So, if you look back
at the sample code this is the
reason why we defer location
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
updates from within
the location,
didUpdateLocation
delegate method.
And so if you use this
as your entry point
into the API you've already
armed yourself to retry
when it's probably
most appropriate.
And you're not going
to constantly spam us
with deferred updates just
because the previous one failed.
A couple other notes
on this API.
The first is that we actually
deliver LocationUpdates
immediately in the foreground.
If the user is actively
looking at your device,
their own device, then
there's no way for us
to sleep the device
because the device is on.
Similarly if they're looking
at your application
there's a good chance
that they actually want to
see your traces being drawn
in real-time on their map.
And so we're not going
to penalize you for that
and actually we'll keep
track of your foreground
and background behavior for
you and guarantee that as long
as you're in the
foreground whatever--
we're going to temporarily
ignore deferred updates
and just keep giving
you live ones.
And when you back into the
background we'll gladly try
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to sleep.
Now distance is completely
optional.
If you don't care about how far
you want to go but you just want
to tell the user how far they've
gone every fifteen minutes you
can just leave the distance
field off by specifying
that you want it to be
the maximal distance.
Similarly if you want to
motivate people just by distance
and not by time,
you could specify
that you don't care about time.
And, of course, together
these are optional--
these are both optional
so the reality is
that if you specify a max for
both fields we'll run as long
as we are technically capable
of running and then when we run
out of memory on the chip
we'll wake up temporarily,
give you the current
location updates that we have
and then go back to
sleep and keep going.
And we can rinse and repeat
this until the next time
that your user-- the next time
that your user launches your
application and then you decide,
hey I want to defer-- I want
to cancel deferred
updates by disallowing it.
And lastly, this is
actually available starting
with iPhone 5.
And this is why we
actually weren't able
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to talk about this last year.
So, it's actually
available starting in iOS 6.
So, if you're curious about
targeting your APIs against 7
and 6 this API is
already available;
go ahead and try using it.
So, with that I'd like
to move on to a couple
of New Region Monitoring
Features.
The first feature I want to talk
about is solving a little bit
of a problem; it's a minor
problem where let's say
that your user decided that they
wanted to monitor for arrival
at a particular location.
Let's say and you already
have a Placemark for it
that you've already
done a Geocode for.
So you take the region out and
you start monitoring for it.
That's all pretty simple, but
let's say that I was trying
to remember that tomorrow
when I get to Mascone Center
that I want to remember
to talk to somebody.
Now, if I do this
then the result is
that when I leave Mascone
tonight my application is going
to launch, it's going to run.
It's going to realize this
location update was not really
relevant to me and
then go back to sleep.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, it would be nice if we could
save that step and allow you
to specify that you only
want to be notified on entry
and you don't care about
being notified on exit.
And so by separating
these two entry criteria
or by separating the
notifications between exit
and entry we can launch
your application less often
which will allow your
device to sleep more,
which is good for your users.
And these properties
that are hanging off
of the CLRegion object
and if you specify
them before telling us
to monitor then we'll go ahead
and honor what your request is.
And they both default to yes.
This is for backwards
compatibility and just
because it's kind of a
reasonable default value
when you haven't told
us anything otherwise.
Next, another Region Monitoring
tweak that we've made is
to address specifically the case
where you're trying to monitor
for a user's departure
from a particular location.
Let's say you want a
temporary reminder saying hey,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
remember your car keys.
That way if you get six
blocks from your friends house
and go find your car you don't--
you actually can unlock the car
as opposed to waiting and having
to go back to their house.
So, this relatively
easy to achieve,
assuming you already have a
recent location then you can
construct a circular region
around this user's location.
And, of course, you can use
the new properties too to say
that you really only
care about exit.
But, once you start a
monitoring for this region,
Location will go off and try to
figure out where the user is.
Now, depending on how long
ago that last location was
and how fast the user is
moving, it's entirely possible
that at the time that the
fence initializes your user has
already left their friends house
at which point there is no
exit notification to give you,
because there is no exit event.
It's simply that we
started outside the fence.
So, in iOS 7 we're providing
a new delegate method.
LocationManager did
determine state for region.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now anytime that we
determine the state
for your region we
will call this method
and if you say compare
the fence identifier
against the departure
fence and then check to see
that that state is outside,
it doesn't really
matter how you got here.
If it's a departure fence
you've already departed.
It could have happened before
the fence monitoring started.
Now you what the state is and
you can tell your user about it.
This delegate method is
available on Location.
This is the delegate
matter method
that if you implement
we will call
and we'll call it whenever your
application is already running.
We won't relaunch your
application for all
of the little details, but
we will gladly tell you
about the state for a
region in detail as long
as you're currently running.
And there's three
possible states.
The first is the fact that
you are inside the fence.
Obviously the other
option is outside the fence
and the third option is
simply we don't know.
And usually this
happens when your--
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you've just installed the fence
and so we haven't had a chance
to start monitoring for it yet
or alternatively it could happen
if the device was rebooted
because we don't track--
we don't persist
where the user was.
If you reboot the device we
temporarily lose the state
of all of our fences and we
have to reestablish ourselves.
This is why a Mac Book
Pro if you shut it off
and then you wake-- and
you reboot it inside
of a new location
your fence won't fire.
It's because we don't secure--
we don't save your location
information to disk.
So, with that there's one
more thing and that is
that this is queryable.
So if at any point in
time you're curious
to know whether your fence
will fire and try to figure
out which side of the
event criteria you're on,
you can ask us for the
state of the region
that we're already
monitoring and we'll tell you.
This is particularly useful
if the radius boundary--
where the user is and where
the center is and the radius
in a straight line suggests
that you're inside the fence.
But if the user has
been moving inside
and outside the fence every
couple of seconds we're going
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to coalesce those updates
into something that's
a bit more filtered
and much more reasonable
for the user
so they're not constantly being
spammed by new notifications.
So, in that case it's
useful to query us
to know what the
current state is
so that you can decide
whether or not--
so that you can be
in sync with us.
So, we'd like to move on to talk
about a case that many of you
that have retail shops
are familiar with
and that is the idea of
basically how to interact
with your user in a
meaningful way while the user is
at your store.
So, to do this, I want to talk
about my side business,
Jay's Donut Shop.
Now, it's a good point in
time to remind you you're all
under NDA which means that
you can't tell my boss
that you've been moonlighting.
[Laughter] So, hopefully
my store has been quite
successful lately.
I've got a lot of stores
in a lot of locations.
And so I'm looking to expand
and the most obvious choice
for me is build an iOS app.
It helps that I actually
know something about iOS
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and I can familiar with
this so it's not that hard.
But engaging my customer
in their store is useful.
You know knowing where stores
are, what they're hours are,
what nutrition information
each donut has that's useful
information that
anybody could have.
But actually coming up
with a rich experience
when my user's already in my
store and want to be engaged
with my donut shop
is really cool.
So, my first prototype for
this experience was resolved
around welcoming my
customers to my shop.
Being a location
engineer I already know
that we have region
monitoring in API.
So, I took my first
shop in Cupertino
and I started monitoring
for that region.
Now anytime I showed up at my
donut shop I got a notification
saying, welcome to Jay's.
Well that's great but let's
go ahead and expand it
out to all my other stores.
So, we first installed a fence
in San Francisco and then,
of course, there's
a shop downstairs
and then there's a shop over in
Twin Peaks and then there's one
in San Jose and Los Angeles
and New York and Denver
and quite frankly
this is both tedious
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and at some point we hit a wall
and we can't actually monitor
for all of these regions.
So, this is not going to work.
What would be nice is instead
of monitoring for a region
on the globe we actually
monitored
for what we're actually looking
for, which is Jay's Donut Shop.
And so conceptually
this is what we would
like to achieve is just
specify that whenever I'm inside
of Jay's I'd like to know
that I'm inside of Jay's.
And so to set out to build this
core location team first looked
at the actual physical store.
And inside of every store
there's a glowing employee
sitting behind the counter
saying, "Welcome to Jay's.
Have a donut."
So when we looked to build
something in the virtual world
around this we wanted something
that approximated this behavior
and we noticed that a lot
of stores already are switching
their cash registers to iPads.
So, wouldn't it be nice if
there was a way for your iPad
to communicate with
your customer's iPhone
to tell them they're
inside of Jay's Donut Shop
and for your application
on their phone to pick up
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and give them an
immersive experience.
Wouldn't it be even better if
instead of saying you're inside
of Jay's to actually be able to
encode some extra information
like you're inside
of the Cupertino store,
try an apple fritter.
[Laughter] So this is
what we set out to build.
And to do this we
came up with a concept
that we're calling iBeacons.
And so with an iBeacon take a
Bluetooth device like an iPad
and if we set a field around--
if we start advertising
a particular packet
from that Bluetooth device
and we can basically end
up creating a field around the
device that is roughly a circle
and if a customer walked by the
store and then entered the store
with their own iPhone our iPhone
could see this Bluetooth low
energy field and know
that I'm inside the store
and change its behaviors
based on that.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And similarly when
the user leaves
that store we can know this and
we can have an exit notification
as well and this allows
you to build context
around multiple places.
You know any store, any Jay's
store is roughly equivalent
because each one has a beacon.
It doesn't matter where
it is in the world.
And so going back to code, this
is what we were trying to do.
And to make this actually
feasible in practice you have
to realize that Jay's
Donut Shop is not unique.
Jay although not the most
common name isn't even unique
in the donut world and
there's a lot of competitors.
So, the first thing I'm
going to need is I'm going
to need a universal
unique identifier
to represent Jay's Donut Shop.
Now if I go into an OS
X machine and I create--
I use uuidgen I can
get one of these.
And so, once I've done this
once I now have an identifier
that I'm going to use
to represent my stores.
And the odds that anybody else
could accidentally use this
identifier to represent
my store is very slim.
Now obviously somebody could
maliciously copy my identifier
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
but in general this is a unique
way for me to see my stores.
To turn this into
practice I'm going
to have an application delegate
that's going to go ahead
and construct a uuid
object from this string
that I've precomputed and
also going to store the fact
that this is Jay's Donut Shop.
Uuids are great but it's
also much easier to code
if you have a human
readable identifier,
especially if you're
going to deal
with multiple beacons
inside of one app.
And, of course, this is based
around a location manager
so you're going to
have to create one
of these and set yourself up.
Now when I'm ready
to start monitoring
for my stores I can implement
a function that looks something
like this,
startMonitoringForStores.
And all I have to do is
construct a CLBeaconRegion
object, specify the proximity
uuid that I've generated.
This is the one that all of my
stores are going to advertise
and then specify identifier.
This identifier is what uniquely
identifies it to your instance
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of core location such
that if you decide
to change its parameters
after the fact
or uninstall it you can use
that identifier to do so.
Lastly,
startMonitoringForRegion.
This is the exact same
region monitor in API
that you're already familiar
with and now it's been expanded
to handle these BeaconRegion
objects.
This means in turn that when you
get an entry notification you
handle it exactly like you
would a geolocation update.
Specifically saying that hey,
is the identifier of the region
that I've entered the same
as the one that I care about?
Okay, go ahead and tell the user
that they are at
Jay's Donut Shop.
This is a great first
step at a product.
Now my friends can, that
are trying this app can go
to a store and get
immediately notified
that hey look you're
inside of Jay's Donut Shop.
But one of my friends came
back to me and said hey look,
you've got that Jay's Donut
Shop over at Valley Fair Mall
and whenever I go inside there
and I go buy some
shoes the result is
that my phone starts vibrating
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
because I go by Jay's
Donut Shop.
So this is relatively annoying.
The reality is that users
don't necessarily care
that they're inside of Jay's.
They're usually seeking to
interact with your store.
And when they're ready to do
that they're perfectly capable
of pulling their phone
out of their pocket
and turning their display on
and launching their
application themselves.
So, but we can still speed the
process up by letting you know
when they've turned on their
phone inside of a store.
And so to do that
there's an added property
that BeaconRegions support which
is notifyEntryStateOnDisplay.
And now any time a user
turns on their phone inside
of my stores my application
will get a launch event
and I'll have the
ability to respond
to the user's interaction.
And, of course, we can
disable the notifyOnEntry.
This is spurious wake
that wasn't really
relevant to the user.
There's no reason to know
that we've walked by Jay's
or even stepped into
Jay's until I'm ready
to interact with my phone.
And we're going to
leave the notification
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on exit around in a second.
But now if I monitor for
regions this way that--
my friend that's walking through
Valley Fair doesn't have their
phone vibrating in their
pocket all the time,
they can go get their shoes
and then when they're ready
for a donut they can now
interact with my app.
The problem is that when
they interact with their app
in line they get that fantastic
notification welcome to Jay's.
Here's all these cool
things you can do.
They buy their donut, they
sit back down at the table.
They're drinking their coffee,
they pull out their phone
to check their email;
hey welcome to Jay's.
So, it's important
to keep in mind
that this will fire every
time their display turns
on if they're inside your store.
So, what you're going
to want to do is
if you haven't already presented
a notification then go ahead
and present a notification.
If you've previously
notified them that hey,
you're in Jay's you
don't really need
to have another notification pop
up on their lock screen or worse
over what application
they're trying to use.
So, this is on you guys
to figure out how to not--
to keep track of the fact
that you're inside of a store.
And it I might be a
good idea to then--
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
track when you leave the
store so any notifications
that are still lying around on
the lock screen you can clear
and similarly you
can rearm yourself
for the next time the
user uses the phone inside
of a different store.
So, that's a great first
step, but the reality is
that welcoming people to Jay's
Donut Shop doesn't really buy
them much.
What can you do with
a warm welcome?
That's what my employees
are for.
I pay them a lot of money to be
very smiley and friendly to me.
So, wouldn't it better--
so let's come up with
a use case around this.
So, one of the things
that you can do
on my website is you
can order donuts online
and you can have them ready for
pickup at a store which means
that you know you go home,
you print off a receipt,
you bring the receipt
in the store
and they bring you
a box of donuts.
Wouldn't it be better
if you could turn your
iPhone into that receipt?
The reality is that we have
had this technology for a while
and anybody can do it.
What's going to make my
application unique is
that when I approach the cash
register my phone is going
to know that I'm at the
cash register and it's going
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to present me a notification
saying, hey now's a good time
to pull out your receipt
because your donuts are ready;
you can pick them up.
To do this we need to know
approximately how far we are
from the cash register
not just the fact
that we're physically
inside of Jay's Donut Shop.
So, to achieve this iBeacon
supports a notion of ranging.
And so if we took that same
Bluetooth little energy signal
and if we kind of
conceptualize it as a field
where the closer you are to
Jay's Donuts the stronger
that signal's going to be
and the further away you are
the weaker its going to be,
we can ascribe rough
categories to that distance.
So, you're immediately
on top of the beacon.
You're somewhat close by or
really far away or we don't
where the beacon is, probably
because we've never
seen it before
or we can't see it right now.
So, with this rough notion
of ranging we can actually
achieve this notification that's
specifically tied to a
location inside of my store
and not just the
store more broadly.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, going back to my region
monitoring example when I know
that my user's turned on their
phone inside of the store,
because again I'm
not notifyingOnEntry
when the display is on.
Now, whenever this happens I
can start ranging for beacons
in this region and so any beacon
in the store that I can see
after I start ranging
I'll get an individual--
I'll get an update that
coalesces all of them
and tells me the approximate
range to each of them.
So, locationManager
didRangeBeacons
In Region will have this array
of beacons that I can see.
And as long as that beacon count
is positive I can take the first
object in that array,
which is roughly equivalent
to the closest beacon.
Now, you have to realize that
this not 100 percent precise
and so it might not actually
be physically the closest,
but it is the one that we're
seeing and its roughly--
it's approximately the closest.
And more importantly in
Jay's Donut Shop there's only
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
one anyway.
So, if I check to see if
that proximity is immediately
in my vicinity then
now's a good time
to show the receipt
notification.
And of course, if all the
beacons drop down to zero
that means that I've
left the store
and I can't see any beacons
and so it's a good time
to hide the receipt.
And similarly to before,
we want to bookend this
with clearing out notifications.
So, when we exit my store it's
a good idea to stop ranging
for beacons in the region,
because you're not going
to see any more if you're
not inside that field
and similarly hide the
receipt if you haven't already.
So, this is a great way to do
approximate ranging to things
and know where you are
and relative to a beacon.
So what beacons actually
are is they support a number
of properties.
The first is the proximity uuid.
This is the universal
unique identifier
that you've told
us to monitor for.
And when we find the
beacon that matches it,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
this is the beacon
that we return to.
And every beacon that--
every beacon has one.
And when we get-- when we see
one we have the approximate
range to that beacon.
And this is one of
four types the unknown,
immediate, near or far.
And lastly there's
these two other fields,
a major and a minor number.
These are two 16 bit values
that are completely customizable
that you can program
onto the beacon yourself.
What can you do with these?
Well, in Jay's Donut
Shop I had this problem.
I had a friend that like
really liked Jay's Donut Shop
and he went to the shop
multiple times a day.
And when he tried to use my
pickup order system he went
to one store in the morning and
then his donuts were available
at a different store
in the afternoon.
But when he got to the store
in the morning he
got a notification.
It would be like hey
your donuts are ready.
So, if we encoded the store
number as the major identifier
and we got, read that off the
beacon as we arranged for it
and we compared that to the
receipt that I already knew
where the store was--
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which store was involved
in the purchase,
now I can notify the user only
when they're at the right store.
They go to the wrong store.
I'm glad you like donuts,
but they're not going
to get the donuts they
previously ordered they'll have
to get some new donuts.
And so, this is just
one example.
A common example is
setting the major identifier
to represent a particular store
location and so you can monitor
for a uuid of your
stores that's universal
across all of your stores.
But the major identifier
is just tied
to this one particular instance.
So what about the minor ID?
Forget the stores, what
can we do with a minor ID?
Let's go back to the
original donut shop example.
Welcome to Cupertino,
try an apple fritter.
If each store which
we're representing
by a major identifier also
advertised a particular donut,
that it was its particular
specialty,
now without even bothering
to hit the internet you could
just look up for that donut
on your database in your app
and say hey look this number
corresponds with apple fritter.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Tell the user that if you're
in Cupertino you really should
be trying an apple fritter.
And so this is just one example
of how you could customize major
and minor for your application.
Let's look at another example.
Let's look at something
bigger than Jay's Donut Shop.
Let's take a department store.
Now you can monitor for all
of your department stores
and when you're inside of
a department store you know
which one you're at, but all
of your department stores
are pretty much uniform.
They all have the
same departments.
What if each department had
it's own beacon inside of it.
Again this are Bluetooth
low energy devices so its--
will be possible to manufacture
relatively cheap ones
and we're intending to release
a Bluetooth profile for those
of you that are familiar with it
that will allow other
manufacturers to produce these.
But if you embedded one of
these cheap devices inside
of each department now when
your user is inside the store
and they're at the jewelry
section and they pull
up on their phone they could
see a list like current sales
or promotions on jewelry.
Or if they walk into the
menswear section they could
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
realize Father's Day
is coming up in a week.
It might be a good
time to buy dad a tie.
These are the types
of specific things
that you can do once you
know more information
about a particular beacon
and how far you are to it.
You could have a museum where
each painting was tagged
with different beacon and you
could pull it up in your catalog
of paintings and know all of the
information relative to that,
maybe that section of the
museum that you're in.
There's another example
and that is keep in mind
that these are small devices.
They're mobile.
You can put one in your pocket.
You can walk around with it.
You could also glue one
onto the side of a bus.
Now if you did this and you
encoded the major identifier
as the route information
now when you're seeing a bus
and you're looking at your
phone you could know exactly
where this route takes you.
And, in fact, we already
code this in human lands
to integers anyway, because
quite frankly bus numbers are
sometimes easier to deal
with than route names.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
But there's an added
problem with buses and trains
and that sometimes a train
might run express versus not.
And if it's going to run
express it might only stop
at a handful of stops.
So if I encoded the particular
bus number on a minor identifier
and my user was using my
transportation app in a station
and was ranging,
when that bus pulls
into the station they could
immediately know hey this is the
bus that's going to take me home
or no actually this is going
to skip my stop; I should
wait for the next one.
This is some important
information that you could--
this is just one
example of information
that you could encode
that's contextually relevant
to the user.
Now I mentioned that
we're planning
on allowing other people
to manufacture beacons.
But for starters
let's take something
that you probably already have
and turn it into a beacon.
Modern iOS devices that are
capable of Bluetooth energy are
in scanning for beacons can
also themselves become beacons.
And so if you create
a beacon region
with the same proximity uuid
major value and minor value
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that you'd like to scan for,
then you can actually ask
for a location to encode that
information as peripheral data.
And you can then pass that on
to a core Bluetooth
peripheral manager
that you've already
instantiated inside your app
and you can start
advertising that data.
And of course this
is calibratable
and so you can specify
exactly how loudly
that beacon should advertise.
So, if you've got a small
store you might not want
to shout quite as loud,
that way it doesn't blast
out into the street, but maybe
if you've got a bigger store
you need a bigger field
and this is tunable.
And there's going to
be sample code online
for a project called Air Locate.
It's both going to show you
usage of our API in terms
of using beacons for
fencing and ranging
but also turning a
device into a beacon
and letting you experience--
guiding you through
the calibration process
of exactly how to tune
the advertisement suitably
for your store.
So, tying beacons back
into the CLRegion API.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Previously we had
a CLRegionObject.
This is what all of the
APIs could take in terms
of a startingMonitoringForRegion
for getting the current
list of regions.
So, to expand this
to BeaconRegions we
subclassed CLRegion
to support a CLBeaconRegion.
Now you might be aware
that because the CLRegions were
geared towards geospecific data
they had a center on the
earth and they had a radius.
This doesn't really make sense
in the context of a beacon
which could be glued to a bus or
kept in your pocket or just is--
doesn't really have a center.
So, we refactored the code
and we made available a new
class, CLCircularRegion.
So, now in iOS 7 BeaconRegions
and CircularRegions are
your concrete classes
and CLRegion is just
this abstract class
that the APIs support
for monitoring.
And we're-- so we've
deprecated CLRegion.
If you're targeting 6 and
7 and you need to be able
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to be backwards compatible
go ahead
and keep creating CLRegions.
They'll still work like
CircularRegions did on iOS 6
and they'll be backwards
compatible.
But if you're just targeting 7
and you're leveraging the beacon
APIs obviously you need beacon
and CircularRegions as
your preferred target.
So, in summary please be aware
of the multitasking changes
with a little bit of--
a little simple check
to your application, your
UIApplication instance.
You can figure out whether
or not these are exchangeable
behavior for your application
and you could tune their
experience to make sure
that they're aware of what
limitations they've placed
on you inside of
the settings pane.
Similarly if you have a fitness
application, please go ahead
and defer location updates.
Honestly it's about an
hour's worth of work
to make your application
defer updates available
or support deferred
location updates
and 40 percent battery savings
is kind of the upper bound
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of what you can achieve
if you use this.
So, it would be really
great to just take
that little bit of
effort to do it.
And lastly iBeacons
are brand new.
We've just scratched the
surface on sort of the things
that you could even
achieve with them.
And I'm sure that there's
going to be many more use cases
that you're going
to surprise us with.
So, please go out
and experiment.
[ Applause ]
>> Thanks.
So, if you need more information
Paul Marcos is our Evangelist
for our team, pmarcos@apple.com.
If he can't answer a question
for some reason he can get
in touch with one
of us and he can--
he's a great frontline resource.
Documentation is always
available online and, of course,
you can go to the
Apple Developer Forums.
What's New in Multitasking,
already happened on Tuesday.
This talks about the high level
system multitasking changes
and it would be a really good
idea to review that session
if you haven't already,
especially with regards
to location.
And if you're going
to be leveraging the
advertisement feature
of iBeacons then go ahead and
check the Air Locate project
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and also review the
core Bluetooth session.
MapKit was this morning
and there's a bit more
on it this afternoon and
the app store guys are going
to be talking about using
region monitoring inside
of the app store app tomorrow.
So, that might be a
good idea to check out.
So, again thank you for
coming and thank you
for making fantastic
applications.
[ Applause ]