See what's new in Core Motion. Learn how your application can take advantage of the motion sensors on iOS devices. Walk through new features of the pedometer and learn how to use the altimeter to take your app to the next level. Get personal with motion APIs and sensor data on the Apple Watch. Run through a demo that uses motion-context awareness to make an application feel smarter!
ANIL KANDANGATH: Good afternoon and welcome.
My name is Anil Kandangath and today I'm going to talk
about what is new in Core Motion.
We have quite a few things to talk about.
But today we will stick to a few key points.
We will begin by talking about the Apple Watch.
We have a new platform and we will talk about how
to bring your Core Motion apps to the Apple Watch.
We also have new updates
to the pedometer including some new APIs.
We will also talk about the altimeter
which is a sensor we introduced in the iPhone 6.
Gabrielle will then walk us through an application
that uses Core Motion in a really, really interesting way.
I've seen it and it's pretty awesome.
So let's get started.
Now this is not an introductory session
but we will cover enough Core Motion concepts for you
to be able to follow along even
if you are not intimately familiar with Motion itself.
But for those of you here
at the conference we do have a lab immediately following
So please come by with all your questions.
We have the engineers and scientists on hand.
If you have no questions, congratulations.
ANIL KANDANGATH: Still come by
and tell us how you are using Core Motion in your apps.
We would love to hear from you.
We do have some great past sessions on Apple developer
where we go into great detail about motion sensing
and motion activity and the pedometer.
So do check them out.
Let's get started.
Now, motion sensing has come a long way
in iOS since the early days.
We will begin with just a quick overview
of how things work today.
This is a traditional motion sensing architecture.
You take some sensors hook them up to the main processor
and the drawback should be obvious.
Any time you want to access sensor data,
you do have to keep the main processor active.
This severely limits the kinds
of applications that you can write.
So we thought we could do better.
Starting with the iPhone 5S we introduced a motion coprocessor
that we called the M7.
This is a tiny processor whose sole job is
to process Motion data.
It can chug along all day long and only turn
on the main processor when it really needs to.
This is great for the battery life of the users.
In iPhone 6 we introduced the M8 processor
and new sensor, the altimeter.
This is what motion sensing looks like today on iOS.
So what does it get you?
Well, if you take the sensors
and access data live you do get not just the raw sensor data
but also features built on top of the sensors
like device motion which gives you the altitude of the device
or the pedometer or motion activity.
On platforms that have the altimeter you also get access
to the raw pressure, altitude changes and flights of stairs.
So that is live data from the sensors.
But the promise of the motion coprocessor is
that you can do more than this, right.
Indeed, you can.
You also get 24/7 access to motion activity
and the pedometer and on platforms
that have the altimeter you also get flights of stairs 24/7.
So this is what you can do with motion sensing on iOS today.
So what does motion sensing look like on the Apple Watch?
Well, the Apple Watch also has a coprocessor
and it has an accelerometer
which means you get the same 24/7 access to motion activity
and the pedometer and in terms of live data you get sensor data
in addition to these two.
So if you are thinking gee, this all looks so familiar.
Maybe Motion is very similar
on the Apple Watch too, you would be right.
Most Core Motion APIs on iOS are available on watchOS,
and not only that most Core Motion APIs behave the same
on iOS and watchOS.
So this is a quick run down of the features we have
on both OSs.
But the Watch is fundamentally a different platform.
So there are some things we need to know
as we build our applications for the Watch
and I'll go through them.
We'll start with motion activity.
Motion activity is what gives us contextual information
about what the user is doing.
You can tell if they are walking, running,
driving, cycling, et cetera.
And the stage that you can obtain are very much dependent
on the platform and how it is used.
So this is a quick summary of the states that you can get
on watchOS and you'll notice that you can get access
to walking, running, cycling, and stationary states.
And that's motion activity on the Apple Watch.
Developers have wanted access to the sensors itself
and we do provide access to the accelerometer
through the familiar CMAccelerometer API.
And that should be all there is to the accelerometer
but it is a different platform
and there are some considerations
that we have to keep in mind.
The first is that you are app may get a limited amount
of processing time.
There are no real background processing modes in the Watch,
so your app pretty much runs
when you are showing up on the screen.
And the screen may turn off for many reasons.
The screen may time out.
But the Apple Watch screen is also designed to turn on only
when you're looking at it.
So if you want to turn the screen away from you,
there is a good likelihood the screen may turn off
and your app may not get processing time after that.
So given all these considerations
in mind there are a few best practices I would
like to talk about.
The first is to design your app to only expect data
when the app is on screen.
Now, I know this is easier said then done
but something to keep in mind.
The other is as you are accessing a streaming,
a stream of sensor data you have to ensure
that you can handle your task being suspended
in a graceful way.
And fortunately we do have a way to do this
If you use this API performExpiring
ActivityWithReason, you can perform your sensor data
processing as a block in this API
and this will inform your block that your task is
about to be suspended so you can do the right thing.
That is the CMAccelerometer API.
But some of you want more, a lot more than that.
In fact you wanted to get access to sensor data
for a long period of time.
So today I'm pleased to say
that for the first time ever we are providing access
to historical sensor data as the historical accelerometer.
Now what does this do for you?
It allows you to access data for long durations.
For really long durations.
And you can access this data even
when your app is not running.
So this enables you to perform your own custom algorithms
on top of this long streams of sensor data.
This is really cool and we expect you
to make really cool apps with this.
So how do you do this?
We have a new API called the CMSensorRecorder,
and this enables you to initiate historical sensor
Now keep in mind, this is a key difference
between this historical API
and the other historical APIs we have such as the pedometer
and motion activity where you do not really need
to initiate any recording.
But for the SensorRecorder you do need to initiate it,
and the data is recorded at 50 Hertz,
and you can query it for up to three days.
So that's how you use the SensorRecorder.
In terms of the implementation, here is how we do it.
The first thing you want to do is initiate recording data
and do it by saying recordAccelerometerDataFor
and provide a duration.
Once you do this, the device may go to sleep.
Your app may get suspended.
It's all okay.
Later the user may come and launch your app.
When they launch your app you may decide to query
for sensor data and you query it by saying accelerometerDataFrom
and provide a time range.
The accelerometer data will then be returned
for the time ranges specified.
And it should be obvious that the time range can be a subset
of the time that you have been recording data for.
Now, the data is returned as a sequence
of CMAccelerometerData objects.
Cast your mind back to what we said
about handling task suspenses gracefully.
You will encounter the same problem here, too.
So as you are processing this big stream
of historical data you do have
to visit our old friend NSProcessInfo.
Now, this will inform you when your task is
about to be suspended.
So if you look at the accelerometer data object,
it contains not just the acceleration part you're
familiar with, but also a startDate.
And you can use this startDate as an anchor
to make sure the next time the app is launched you can query
from this point onwards.
So that, is how SensorRecorder works.
Now, this is great, but as you show there is one consideration.
Well, two, power and performance.
Now, the SensorRecorder is a powerful API
but with great power comes great danger.
And the danger here is that you may not have enough time
to process large strings of sensor data.
So a few best practices again.
The first thing is to, and this may be obvious, is to record
and query only data for the minimum duration required
by your app.
So if you are a work out app you probably don't need 12 hours
You can probably get by with a couple of hours of data.
The less amount of data you query for,
the easier it will be for your app.
You should also know the sensor data rate requirements.
Now, the data is available at 50 Hertz,
but unless you are planning to extract features from that data
that require a high sensor rate you are better off just dropping
data and process less data.
So a few best practices and you should be good.
And that's the Core Motion update for Apple Watch.
As you've seen we had a lot of the familiar APIs
and we also have access to historical sensor data.
This should be really great, and you should be able
to make really cool application with this.
In terms of writing Watch applications,
we did have a session earlier this morning
that you can probably go watch now.
For the rest of the talk I'll focus on iOS and I'll begin
with updates to the pedometer.
This is the pedometer that you are familiar with.
Steps and distance.
A quick recap.
The pedometer is designed
to give you consistent performance
across body location.
So whether it's in your hand or if it's in your pocket,
the performance is supposed to be consistent,
and it is also consistent for varying pace.
Now a great feature of this pedometer is
that it adapts to the user.
So the more the user uses the pedometer, the better it gets
by calibrating itself to the user.
In iOS 9 we are making one big improvement to the pedometer
which is it incorporates GPS when possible.
Why do we do this?
Well, you may have an app
that is already subscribing to location.
Maybe you are trying to plot the user's track
as they go on a run.
When you do that, the pedometer senses
that GPS data is available
and it gets more accurate by using it.
Well, why is this so critical?
So take a look at this run that a colleague
of mine did in San Francisco.
San Francisco is urban canyon.
It has tall buildings and it can be a challenging environment
for any GPS.
If you look at this segment here,
GPS looks pretty solid here.
If you were to rely on GPS we'd get really good
If you look at a different segment here,
you can see that there's quite a bit
of wander in the user's track.
Now granted there are quite a few pubs along the way --
[Laughter.] but that is probably not really how this person
The pedometer is smart enough to understand
that this is a portion where it should not rely on the GPS,
and it resorts to its own stride-based
The end result if you use the pedometer you get a consistent
performance and that's why you should use steps
and distance from the pedometer.
We have one big API improvement in the pedometer this year.
That is -- well, before we go to that,
let's talk about one you already know about
and that's floor counting.
So floor counting is available
as floorsAscended and floorsDescended.
Because this is part of the pedometer,
there is a pedestrian aspect to it, which is that you have
to actually take steps.
What it means is that you really have to earn your floors
to be awarded floors here.
Let's take a deeper look at how this actually works.
It has a few requirements.
The first is that there is a minimum ascend rate requirement.
There is also a steps requirement.
What this all means for us is that if you were to say go
on a long hike and you walk slow
and eventually you accumulate quite a bit of altitude.
The likelihood is that you won't hit the ascend rate requirements
and we won't award you floors.
But if you are walking in San Francisco
where you have some really,
really steep hills it is possible
that you will get a few floors.
Also because of the step rate requirements if you were
to use the elevator
or the escalator you are not likely to be awarded floors.
So that is how floor counting works in iOS.
Now it's time for the new API.
That is pace.
Pace is something
that developers have long asked us to provide.
We are happy to provide it now.
When we talk about pace, we are referring to currentPace.
So this is really the instantaneous pace
and not the pace as estimated from the beginning of your run.
And it is provided in units of time over distance.
If you are wondering why it is provided in this way and not
as speed, you know, that pace is normally analogous to,
is because for runners, pace is the time taken
to cover a known distance.
If you have been following the Apple Watch updates
on the website, this pace might be familiar to you.
To me this is something that I'm envy just of.
ANIL KANDANGATH: The pedometer has both a live
and historical aspect to it, but pace is only available
when you do live queries.
So just keep that in mind.
Now why do we provide pace?
After all, we do provide distance and a notion of time
in the pedometer, and we could just easily compute pace
The answer in one word is robustness.
If you were to say do some finer difference and try
to estimate pace just from those distance chunks,
we would introduce an acceptable amount of jitter in the pace,
and the pedometer takes care of this and ensures
that the pace estimation is smooth.
The other part is you could try to get a smooth pace
by looking back at a much bigger chunk of the history
and then try to average a pace over it.
But the cost of doing that is you lose the ability
to respond quickly to changes in the user's pace.
Pace from CMPedometer also responds very quickly
to changes and it is responsive.
So smoothness and responsiveness is why you should use pace
And that's pace.
A close cousin of pace is cadence.
And we now have cadence in the pedometer.
Now, what is cadence?
Cadence is the rate of your steps or in other terms,
it is how often your feet are landing on the ground.
We know that the cadence is really important to runners,
so now you can provide cadence
in your apps directly from the pedometer.
ANIL KANDANGATH: So that is our update for the pedometer.
Here is a quick run down of the features across platforms
and note that the pedometer is also available
in the Apple Watch.
Let's move on to pressure sensing.
The pressure is available through the altimeter sensor.
It is available as part of the CMAltimeter API.
And it gives you two things.
it gives you raw pressure which is nothing
but a filtered version of the pressure from the sensor itself
and gives you relative altitude.
Let's take a deeper look at altitude.
When we say relative, it is relative
to the first sample provided.
What it means is that the first sample you get
from the altimeter will have a relative altitude of zero.
And every subsequent sample will be baselined against that.
What do we need to know about the altimeter to use it?
Well, the altimeter is really great for floor level changes.
It is not really great for human level changes.
So you should probably not use it to know
if the user is raising their arm.
The error is not going to be good for you.
There are challenging situations for the sensor
that you should keep in mind.
One is the environment.
The environment might change over time in the same location
and give you a false sense of altitude changes.
For example, the recent cold front
in San Francisco would have changed the pressure enough
for us to think that your altitude changed
by say 15 meters.
You should probably not use the sensor
over long durations of time.
The case that your device is in can also impact the pressure.
If you are using a rigid sealed waterproof case for your phone,
the pressure sensor is not your friend.
In terms of using the API, it should be very familiar to you
and it gives you pressure and altitude in the API.
How fast can you access data from this sensor?
So the first time you make a request, the first sample takes
around 2.6 seconds to come.
Every subsequent sample comes at a cadence of 1.3 seconds.
That is how fast you can get data from the altimeter.
So to summarize, Core Motion now has, is available
on a multitude of platforms.
It is available on the iPads, the iPhones
and also the Apple Watch.
On the Apple Watch we give you access
and not just the familiar APIs but also historical sensor data.
The pedometer has a bunch of really cool updates of its own.
It's more accurate than ever, and it has two new APIs
in the form of pace and cadence.
So it is a well-rounded now and should be great
for your fitness apps.
Now Core Motion has traditionally been used
for gaming, for gestures, for fitness.
There's a bunch of applications for Core Motion,
but Core Motion can also be used to enhance the intelligence
of other kinds of apps.
To illustrate this concept I am going
to invite Gabrielle on stage.
GABRIELLE BADIE: Hi, everybody.
I'm really excited to be here.
As a developer, I never got to attend WWDC, but I spent every,
that first week of June watching all of the sessions
on my computer at home wherever I was working.
I learned a lot of information,
but one of the really difficult things was
that there was too much information.
Even in a given session there is so much to absorb
that when you leave you may even forget all of the things
that you learned in the last hour.
What I'm here to do is to take a few of the great things
that Anil just talked to you about
and see exactly how you might want to use them
in your application and hopefully make them stick.
Now Core Motion is really great because it can't be just used
in a fitness context or gaming context.
What I'm here to show you today is how you can use it
in your app regardless of what category it falls in.
So what can Core Motion do for you?
Core Motion allows you to detect what a user is doing.
You can see if a user is in their car,
going on a run, if they are cycling.
You can see their changes in pace as we've seen,
we smooth that out for you.
And so by using those updates,
we can tell what context a user is in without prompting them
and asking them to tell us.
This makes that experience more magical and our apps smarter.
The next thing we can do is engage the user.
Because updates come in every few seconds we can see how their
pace is changing.
We can see how their altitude is changing.
We can update our app UI quickly and accordingly.
The last thing we can do is reflect back.
And I know that sounds really cheesy,
but one of the great things about Core Motion is
by running all the time we can make it look
like your app is working really hard 24/7
when actually the coprocessor is.
We can look at your activity updates
and your pedometer updates over the last week,
which is pretty fantastic.
So with these three things in mind, I decided I was going
to make a music player.
Nothing to rival Apple Music or anything like that.
I wanted to see how Core Motion could make my app experience a
little bit more engaging and more magical.
Now a lot of music applications have this idea of playlists.
I certainly listen to different music when I'm
in my car I want podcasts, or if I'm studying or working hard,
I'm going to want maybe some classical music,
and different app playlists for working out as well.
By detecting what a user is doing,
my music application can change my playlists accordingly instead
of the user having to select it.
Similarly, by seeing changes in pace we can say hey,
you're going on a slow jog or maybe you went really fast
and climbed up a really big hill and we are going
to play you a really exciting song to make you feel good
about that, or try to match your cadence.
Then there's the reflection piece.
There are two really great things
about reflection especially in the context
of my music application.
One, I can look at data to see how a user has been doing.
Hey, you haven't been running in a while.
Maybe you want to go on a run really soon and maybe you want
to use our application to do that
and listen to your playlist.
At the end of the day I want to motivate users
to come back to our app.
Also I thought it would be really great
if I said the user might want
to know what playlist they were listening
to in the car yesterday.
And so by looking at activity information and paring it
with my information
about playlists I can give that info to them.
So with these three ideas in mind,
let's see what my application actually looks like.
So when the user opens the app, we just want
to show them a basic playlist.
In my case I'm pretty much standing around, right?
We're going to have low intensity music.
Nothing too tough.
As we detect that the user is speeding up.
Maybe they start going for a workout.
We're going to change the playlist
and give them a little more upbeat music.
But this is where the engagement part comes in.
This is where we look at maybe changes in cadence
and maybe changes in altitude, and we really engage with them
and follow along, so we can give them a more high intensity
playlist when they speed up.
Then we want to context switch.
When the user goes for a drive, I want to be able
to give them their podcast or whatever they usually listen
to on their morning commute.
So this is the detection piece and engagement piece.
Next we have the reflection piece.
I want to put this information into interesting pieces
so the user can scroll back and see what they have been doing.
This is where I might tie in kind of that playlist
that they were listening to at different moments in time.
So now that we have an idea of what the app will look like,
let's see where motion activity actually fits in
and what APIs we might need to use for each of these pieces.
First we have the detection piece.
This is something we are going to want to do all the time.
We are going to want to see if a user is driving.
If a user is walking, how fast they might be walking.
So what are we going to need for that?
Activity updates and pedometer updates.
We'll want to be monitoring those and smoothing those out
and seeing which information allows us to determine context.
Next we have that engagement piece.
If the user is walking or running, in my case I want
to see how fast they are going.
Look at that cadence, and also I had that idea of maybe
if they climb a big hill I can give them a great cheerful song
at their achievement.
For that I would need pedometer updates
which includes those pace and cadence changes
and altitude updates as well.
Then we had the reflection piece.
As I said, the great thing about Core Motion is
that they work really hard for me 24/7.
So I can look back and get those historical activity queries
and pedometer queries to put that information
into interesting segments.
So now that I've gone through exactly what my app might look
like, the detection, engagement, and reflection pieces,
and which parts of Core Motion's APIs I would need to use,
I'm going to show you exactly how I coded it up,
at least for the data model part of my application.
I am about to open Xcode.
Before I walk to the computer over here,
be warned that there will be a lot of text on the screen.
Don't be intimidated.
The sample code is already available online.
Don't go open it now, please.
GABRIELLE BADIE: Please just focus
on the segments I highlight for you.
As I said, there's a lot of text on there.
If you focus on those few things and maybe go back and look
at the sample code after the session,
you'll remember the things I focused on instead of trying
to do too many things at once.
As I said, a lot of text.
So as I said, a lot of text on the screen.
I just want you to remember the three parts
that would be detect, engage, and reflect.
As we keep those in mind I am going to go
through these things here
in this data model of my application.
This is just the data model piece.
The rest is for you to explore later.
So the first thing I'm going to want to do is detect.
That requires activity updates and pedometer updates.
Let's look at those activity updates.
Great. A lot of text, right?
So the first thing I'm going to want to do is check
if activity is available on this hardware.
As an Anil noted before activity isn't always available,
so we're going to want
to do those checks before we query for any updates.
The second thing we are going to want
to do is use the startActivitiesUpdateToQueue
In my case I provide an just a simple NS operation queue,
and then I want to handle the data.
Now, activity updates come in pretty frequently.
It's up to you how you want to do the smoothing.
In my case when a user is going on a run and maybe they stop
at a stop light and they are semi-stationary , I don't want
to keep transitioning from the running playlist
to the really slow playlist and back
and forth and back and forth.
So I'm going to want to do
that application specific smoothing myself and I leave it
up to you to do what's best for your application.
Let's look at pedometer updates next.
Great. As you can see,
the PedometerUpdates API is very similar.
I'm also going to want to check if step counting is available.
Even though we assume that activity might be available,
that doesn't mean that step counting will be available
Assuming that that's true, I'm going to startPedometerUpdates.
This API allows us to provide a date.
If you are in a more journaling context you might want
to start these updates at the beginning of your day.
In my case I want to look
at them during the lifecycle of my application.
So I start these updates from right now.
Now, there's a really important thing I want to point out here.
We may get an error.
One of the great things about Core Motion is that they do kind
of the: Hey, do you want
to let this app use motion data pop up for you.
But while a user may first open your application
and give you access to motion data, they can go back
at any time in the preferences and remove that authorization.
In that case then we would throw an authorization error
when you try to receive updates.
You are going to want to handle those smoothly
and prompt the user to go into the settings application
and give your application authorization again.
I won't go into it here, but I pop up a simple UI alert view
to prompt to go into settings.
So that is the detection piece.
The next thing I'm going to want to do is the engagement piece.
In my case when I'm looking at activities updates,
I also want to start and stop altimeter updates,
so I'm going to do that here.
I smooth out to see when the user is running or is walking.
In that case I'm interested in altitude updates.
Great. Now you're starting to see a theme here.
First thing I'm going to do,
check if altitude updates are available.
Assuming that's true,
I startRelativeAltitude UpdatesToQueue.
I provide a queue.
And then I handle the data accordingly.
I do check again if there is an error.
And if not, I'm going to want to handle that data
as best serves my application, and I leave that to you
to do as best serves yours.
The next thing I'm going to want to do because I'm not interested
in altitude updates all the time is make sure that I stop them
when I'm not running or walking.
Great. And here, the API is pretty straightforward.
I check for availability.
And I stopRelativeAltitudeUpdates.
Now, I know that when I said we want
to engage the user we are going to look
at pedometer updates as well.
As you may recall I was already looking at pedometer updates
for the lifecycle of my application, and so I don't need
to start and stop those again.
I can use those in fusion with the altitude updates
to give me what I want for my application,
which is to motivate the user through music.
Now, we have the reflection piece.
So here I'm going to want to look at activity updates
so I can provide these in interesting segments
as I showed you earlier.
Great. So the first thing I want you to look
at is we can query activity updates starting from date.
In my case I wanted to look at it during the last week
so that even if we are not looking
at using the application during that week, we can get all
of that data and put it together.
In my case I handle that data and I put it
into interesting segments for me.
I can't wait to see what you guys want
to do with it yourselves.
Again, I know, broken record, right?
I want to handle the error accordingly.
Now, in my case also I wanted to give all
that extra historical pedometer information once I found
interesting walking segments.
So what I'm going to do is down here I am going
to request pedometer updates for a given activity segment.
The first thing I do is queryPedometerDataFromDate.
And I provide a start date and an end date.
In my case I've already put the data into segments.
So I look at the start and end of those segments.
The second thing I want to point out here is that if I want
to make any UI changes I'm going to want to dispatch those
on the main queue, and you'll start to find issues
if you don't do that in your own applications.
So that's it.
That's all I really have to show you
with adding motion to your application.
And it took me like ten minutes or something
so it is actually really easy for you to go back and for you
to do in your own applications.
Now, I really want to show you this app but I'm not going to go
for a run or drive on stage here.
So I will show you what I have been up to
in the last couple days and how
that reflection piece organizing the data
into interesting segments.
Hopefully this will be an iPhone.
Great! So here is my music motion application.
As you can see, I'm not doing very much.
So I'm sitting here in low intensity mode.
Now, let me look at my historical updates.
I'm actually going to start at yesterday morning
and I'll take you through today,
but all I've really done is walk around Moscone.
Yesterday I woke up and I decided to go for a quick cycle.
What I've done, I've -- the app has already figured that out
and put that into an interesting segment for me.
Then I walked to my bus, realized I was a little late
and started running, and then finally made it on the bus.
As you can see, what I've done here is the walking segments
have that mile information, the pace information,
floors ascended and descended, and puts those
into interesting chunks for me.
Now if I were actually developing a music application
in one of these cells I might put attach the playlist
that I was listening to for that segment.
One thing I want to point out as I scroll to today
when I have been walking around Moscone,
I'm not getting any floors ascended or descended.
That's because I've been lazy
and taking the escalator everywhere,
and so I just wanted you guys to notice that as well.
So that's my basic music application.
I'm just going to wrap this up.
So I really hope you guys enjoyed the demo.
I tried to focus on just a few things
so that you can remember them for your application.
Remember, there's the detection piece, using motion
to detect what a user is doing instead of a user having
to tell you what they are doing.
Engaging with them with the push updates from activity,
pedometer, and altimeter, and as well reflecting back
and really using those historical queries wisely.
If you have any more questions, feel free to look
at the Developer Forums.
Please do check out music motion.
It should be on the developer portal.
And for any general inquiries, contact our evangelist.
There are also some related sessions
that are really worth checking out.
If you are here at WWDC, you may
or may not have seen the HealthKit presentation
or the Cocoa Touch presentation.
If you missed them or are sitting at home,
please go check those out online.
I also encourage you to check
out the Core Location presentation as well.
If you really combine motion data with health data
and location data, you can create some incredible contexts
to really enhance your applications.
I really can't wait to see what you guys put
out on the App Store.
GABRIELLE BADIE: Thanks.
Thank you very much.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.