[ Music ]
[ Applause ]
And welcome to Integrating with Siri Event Suggestions.
My name is Sofiane, and I'm an Engineer, working on Siri frameworks here at Apple.
And today, I'll be joined by my colleague, Magnus.
We're really thrilled to be here today to tell you all about how to integrate your apps with Siri Event Suggestions.
Siri is the virtual assistant we all know and love, and with SiriKit, your app can work with Siri, for things like sending messages, requesting rides, as well as expose the key capabilities of your app using shortcuts.
Siri is also deeply integrated across our platforms, adding on-device intelligence to the apps you use every day.
In Calendar, Siri is personal and knows about your reservations to help you get organized, and Siri can then use that information about your reservations to make proactive suggestions throughout the system.
So, on the lock screen, Siri notifies you when it's time to leave, based on traffic conditions.
And when you open Maps, you get Siri suggestions, which make it super convenient to get directions right to your destination with just one tap.
Now, when you get there, Siri can proactively suggest to turn on Do Not Disturb and help you stay focused on what matters.
And all of that starts with the system knowing about your reservations, wherever they come from, whether it's in the car rental reservation in mail, a restaurant reservation in messages, or even when you're booking a flight directly in Safari.
Now, in iOS 13, we're really excited to introduce new APIs for your apps, to integrate directly with this ecosystem.
[ Applause ]
So for example, when you view your flight reservation inside the American Airline app, the app donates that information to the system.
Siri can then use it to automatically show a notification and add that flight to your calendar.
Siri will then go on to make proactive suggestions for that flight, at the right time, in all of the places that I mentioned before.
And all of that intelligence happens directly on the device.
But we didn't want to stop here.
This year, we wanted to extend that deep system integration and promote your app in even more places in the system.
So, in iOS 13, if your app supports check-in, it can get promoted right on the lock screen, taking users directly into your app at the right time.
Also new in iOS 13, with maps, when the time is right, when a user goes into maps, they can get up to date information about their flight, and even get directions, indoor directions directly to their gate.
So Siri is there to help at every step of the way, from the moment you make your reservation to the moment you walk in.
So, by now, I hope you're all thinking that is pretty cool, hopefully.
But how does that all work?
Well, the API is built as part of SiriKit which allow you to do many things, like setting up shortcuts, sending payments, and much more.
And more specifically, everything we will talk about today is exposed as part of the intense framework.
We support reservations across many categories, ranging from restaurants to ticketed events, to various forms of transit, and this year, we're introducing new classes in the intense framework to represent details for all of these reservation categories.
Now, all of these classes inherit from the new IN Reservation Class.
So, for instance, to represent a restaurant reservation, you can create an INRestaurantReservation object.
Those of you familiar with SiriKit will recognize the INInteraction API, which is also used for shortcut donations.
So when a user views a reservation inside your app, your app creates an interaction and donate to the system.
Interactions are made up of an intent, an intent response, which together represent a full user interaction.
Now, this year, we're introducing the new INGetReservationDetailsIntent, an intent response that are intended to capture details that pertain to user's reservations.
This provides a way for your app to share those details with Siri.
Now, the intent response takes a list of INReservation objects, as we just saw previously, which represent your specific reservations.
So here, for example, we are creating an INLodgingReservation and attaching it to the intent response to represent the details of a hotel state.
Now, all that is left for you is to donate that interaction to the system, so that Siri can use it in places like Siri event suggestions, or Siri shortcuts, for example.
Okay, now, let's move on and talk about the three easy steps that your app should follow to take advantage of all these great features.
And first, we will talk about how to create and donate good interactions.
Next, we will look into how to adopt the new reservation actions API, so your app can benefit from the new check-in shortcut feature.
And finally, your app may be launched with a reservation that you previously donated.
So we will talk about various launch scenarios that you should handle.
And now, I'd like to invite my colleague, Magnus, up to tell us all about the API.
[ Cheers and Applause ]
Thank you, Sofiane.
My name is Magnus.
I'm excited to be here today to talk to you about Siri event suggestions.
First, I'll show you a demo of how to use the API, and then we will talk a little bit about the details later on.
Let's jump into the demo.
So, I'm working on this flight app called My Flights.
Let's open it, and see what it looks like.
So it displays a list of all my flight reservations.
If I tap one, I can see more details about the reservation.
I want to take advantage of the Siri event suggestions API, and donate the reservation details when it is displayed to the user.
Let's switch over to Xcode.
Now, my app consists of some view controllers and a server, where I get my reservation details from.
Since I want to donate the reservation details when they're displayed to the user, let's take a look at my ReservationDetails ViewController.
The view controller gets the reservations from the server.
For the purposes of this demo, the server returns INReservations SiriKit objects.
I started doing some work on this already, but there is still some missing code here, marked by to-dos.
Let's go to the server, and see what makes up the INReservation object.
In my server code, I have a method called createFlightReservation, to create and save the reservation so I can access it from my view controller.
I'll create the INFlightReservation object here.
Now, this method creates an INFlightReservation object.
This object contains all the reservation details about the flight.
Let's take a look at some of the properties.
First up is the itemReference.
This is a unique identifier for this reservation item.
It will be used when the system launches my app to tell it which specific reservation item to show.
In my app, the reservationNumber is unique for this flight.
So I will use that for the vocabulary identifier.
I also said a spoken phrase that can be displayed to the user.
I'm using Flight XX815, which is short, and descriptive.
Here are some common properties that are shared among all reservation types.
Like the reservationNumber, and the name of the reservationHolder.
We also want to capture information about the flight.
It's created here in a separate method called createFlight.
Let's jump to the implementation.
Here, I'm creating an INFlight object.
This represents all the details about the flight, such as the flight number, the airline, along with the information about departure and arrival.
I still have some to-dos here, so let's go ahead and fix that starting with the airline and airport information.
These objects represent the airline, and information about the flight departure and arrival.
In this case, the flight is from San Francisco to Paris.
Both airlines and airports are identified using either an IATA or ICAO code.
For airports, this is also used to determine the physical location of the airport.
I'm adding gate and terminal information for departure, since it's already known at this time.
I don't know the gate information for the arrival, so I set that nil.
Next, I also need to specify the departure and arrival time for my flight.
We are using the INDateComponentsRangeClass to represent the departure and arrival time.
For the best user experience, I'm also setting the local time zone, sorry, I'm also setting the local time zone for the departure and arrival airports.
Okay. So we set all the information we need to represent the flight.
Let's go back and look at the rest of the reservation.
I want to provide my users with a great check-in experience, so I want to take advantage of the new check-in shortcut.
To do that, I need to create a check-in action.
Let's jump to my createCheckInAction method.
This method creates an INReservation action, which consists of a type, a valid duration, and a user activity.
In my case, the type is Check-In, and the valid duration is the time when the user can check-in online.
During this time, the user activity I specify will be displayed as a suggested shortcut.
I'll start by creating the NSUserActivity.
I'm creating the NSUserActivity with an activityType that lets my app know that this is a check-in activity when it is launched.
I set the title to Check-In for Flight XX815.
This is displayed to the user in the shortcut, so make sure it's short and descriptive.
Next, I'm adding the details I need to know to start the check-in process when my app is launched.
I add them to both the user info under requiredUserInfoKeys properties.
I also add a webpage URL value.
So the check-in process can be used even if my app is not installed.
So I'm pretty happy with this user activity, but I also need to specify the valid duration.
We're using EndDateComponents range again here.
This time, to represent a start and end time for the valid duration.
In this case check-in starts 24 hours before departure, and ends one hour before departure, so that will be my valid duration.
That's really all we need to create the great check-in shortcut.
Let's go back and summarize what the reservation we created.
Now, we have all the information we need including the reservation details, the flight information, and the check-in action.
Let's go back to the ReservationDetails ViewController, to add the donation code.
So, our view controller already knows about the reservation we just created.
I set up a method here to donate the reservation.
So let's add the donation code.
Let me just remove the navigator, so you can see better.
So I'm starting by creating the intent.
The intent tells Siri which reservation was displayed to the user.
It takes two parameters, the ContainerReference, and the ItemReference.
The ContainerReference uniquely identifies the reservation as a whole.
In this case, I only have a single reservation item, the flight.
So I will use the ItemReference I set on the ReservationItem, as the ContainerReference.
If I have multiple ReservationItems, such as a hotel and a flight, I would create a new ContainerReference to represent that reservation as a whole.
I'll set the ReservationItemReference as property to nil.
This is populated by the system when launching my app.
In addition to the Intent, I also specify an intentResponse, and add my reservation to it.
This informs Siri about what reservation details I display to the user.
Finally, I'll add the intent and intentResponse to an INInteraction, and donate that to the system.
So, now we've written all the code we need to donate this reservation, but there is one more thing we need to check before we can launch the app.
I need to add INGetReservationDetailsIntent, and my custom CheckInActivity to the list of supported activity types in my info.plist.
Luckily, I already did this earlier, so we're good to go.
First, let's recap.
We created and donated an INFlightReservation that contains all the information about the reservation.
Now, Siri knows about the reservation, and can provide proactive suggestions throughout the system.
We also added an INReservation action, to provide a great check-in experience, with a shortcut that is displayed to the user, and takes them directly into the check-in flow at the right time.
Let's see this in action.
So, I'm back in my app.
Let's view the flight to Paris reservation like we did before.
When I view the reservation this time, I see a notification telling me Siri found an event and put it in my calendar.
[ Applause ]
[ Applause ]
I'll tap the notification and see what it looks like.
So, as we can see, Siri used the information I donated to create an event in My Siri Suggestions Calendar.
Now, there is also a link back to my app.
When I tap it, I am brought right back into my app.
So that's great.
However, I don't see the reservation details about the event that I was viewing in Calendar, and I think we can do better.
Let's go back to Xcode and see how to implement app launch.
To handle app launch, I'm going to go to my AppDelegate.
When Siri launches my app, it's going to be launched using an NSUserActivity.
So I need to implement the application ContinueUserActivity, Delegate Method.
I'm adding support for two activity types here.
The first is the INGetReservationDetailsIntent.
This activity type indicates that a user wanted to see details about a specific reservation in my app.
I'll call my handleShowReservation method, which will display the relevant reservation to the user.
The second one is the activity type I define for the check-in shortcut.
This is used when the user taps the check-in shortcut on the lock screen or in search.
I'll call my handleCheckIn method when this happens, to start the check-in process.
So, now handling both cases, let's launch the app and see this in action.
First, let's go back to Calendar, and tap the show in My Flights button again.
As you can see, my app now launches directly into the reservation details for this event.
Now, this is a much better user experience.
[ Applause ]
I also added support for the check-in shortcut, and my flight leaves tomorrow at 2:50 PM, so check-in should already be open.
Let's see how that works.
Now, the check-in shortcut appears both on the lock screen and in the Search UI.
When I tap it, I'm launched directly into the check-in flow of my app.
That's pretty awesome.
[ Applause ]
So let's recap.
We created and donated a reservation.
We provided a check-in action, and we made sure to handle app launch.
This is how we see it, is to take advantage of the Siri Event Suggestions API, to provide deep system integration and the great user experience.
Now, I would like to tell you more about the API.
We'll begin with Donations, and talk about how Siri used the information you donate in places like Shortcut Suggestions, and Calendar.
As we saw in the demo, your app is front and center in the check-in shortcut.
We display your app name and icon along with the information about the reservation.
Again, we use the title you set on the NSUserActivity in the shortcut.
So, make sure you use a string that is accurate and descriptive.
Now, Siri automatically synchronized the reservation details across the user's devices using end-to-end encryption.
So the user might see the check-in shortcut on the device where your app is not installed.
In this case, an iPad.
When this happens, we'll use the web page URL property you set on the NSUserActivity to provide a web base check-in flow using Safari.
So that is a check-in shortcut.
Let's take a look at Calendar.
Now, first up is the Title.
The title is auto-generated by Siri using the reservation details you provided.
As you can see, Siri adds a localized reservation type to the title.
Depending on the reservation type, different parts of the information may be used to generate the title.
So make sure you provide all details as is, and do not prepend or append anything for display purposes.
Next is Location.
Location is a key component to the user experience, and it drives system integrations such as a time-to-leave notification and Maps integration.
For most reservation types, SiriKit uses the CLPlacemark class to represent locations.
You can create the CLPlacemark object yourself, or if your app uses MapKit, you can get it off the MapKit item.
If you do create a CLPlacemark object yourself, be sure to include both location and postal address if you have both.
If you do not know the coordinates, set them to 00.
This will let Siri know to use only the postal address.
Next step is the start and end time of the reservation.
As you can see, the event displays both the start and end time using the user's current time zone, and the time zone of the reservation.
So, make sure you set the local time zone for the reservation or use UTC if you don't have that available in your app.
Some reservation types have a clear start and end time.
For instance, for a flight, use the scheduled departure and the scheduled arrival time.
For reservations like lodging and car rental, use the check-in and check-out time.
If your reservation doesn't have a specific end time, set at nil, that way Siri will use the de-filterization based on the reservation type.
Next is the Notes section.
Siri uses the Notes section to populate it with more information from your reservation details that might be useful to the user, such as the reservation number or seating information.
Be sure you populate all the reservation details for which you have information, as it may be displayed to the user.
Finally, Siri provides a link directly from Calendar into your app.
Tapping on it launches your app, so it can display more details about the reservation.
So, let's take a look at what you need to know to handle this in your app.
To understand app launch, let's take a step back and look at what we're donating.
Earlier in the demo, we donated a single reservation item.
But let's consider a case when there are multiple reservation items.
For instance, a round trip flight.
In that case, we have two reservation items that might share the same reservation number.
As such, the reservation number can be used to uniquely identify a specific reservation item.
For this reason, your app must always provide an additional identifier called the itemReference.
The itemReference must be unique for every reservation item in your app.
How you structure the itemReference is really up to you, as long as you're able to reason about which reservation it belongs to later on.
In this example, we're creating a reservation item by combining the shared reservation number and the specific flight number.
Next, we add the two reservation items to an INGetReservationDetailsIntent response, and to complete our donation, we also need to create the INGetReservationDetailsIntent.
When creating the intent, we need to tell Siri which reservation the user was viewing.
This is represented by the ContainerReference.
In this example, we're donating two flights that are part of the same reservation.
So we are setting the ContainerReference to the shared reservation number, since it uniquely identifies the reservation as a whole.
Finally, we are setting the Reservation Item References area to nil.
This is only used when launching your app, to let it know which specific reservation the user wants to see.
So that's our donation.
Let's take a look at how this information is used when launching your app.
When your app is launched to show reservation details, it will be launched using an INGetReservationDetailsIntent.
This represents what reservation the user wants to see details about.
In this example, we're launching the app with an intent saying the user wants detail about a reservation identified as B9C8.
If the reservation item reference array is set to nil, your app should show a UI displaying this reservation as a whole.
In our previous example, that would mean showing both flights.
The user might also want to see details about a specific reservation, such as one of the flights from our previous example.
In that case, your app will be launched with a Reservation Item References Array populated with a single item.
This will be the item reference you set on the INReservation object for this reservation.
In that case, your app should show a UI displaying details about only the specific reservation.
Before launching your app, we wrap the intent in an INInteraction and NSUserActivity object.
With the activity type, set the name of the Intent and launch your app using that, like we saw in the demo.
So, we looked at how Siri uses the reservation details you donate, and how that information is used later on to launch your app.
But as we know, life happens.
A user might change or even cancel their reservation, and that can happen inside or outside your app.
For instance, from a web page.
Let's take a look at how to handle some of those cases.
First, let's talk about when is the right time for your app to donate.
In this example, the user is looking at details for a specific reservation.
Now, this is an excellent time for your app to donate, because like we saw earlier in the demo, we might show a notification to the user.
Seeing the notification and the reservation details at the same time provides a great contextual user experience.
But life also happens when your app is in the background, and users should always have up to date information.
So a new or updated reservation information becomes available, donate that from the background.
In that case, we won't show a notification to the user.
So those are great times for your app to donate, while there are some not so great times for your app to donate.
As we showed earlier in the demo, your app should not donate when showing a list of unrelated reservations.
Showing a notification at that point might surprise the user because of a lack of context.
To provide a seamless experience, your app should not provide UI elements that explicitly donate to Siri.
In this example, the app should donate when the reservation details are being displayed.
Next, let's look at some changes that might happen to the reservation.
Here, we use the example of a user selecting a seat for a flight.
We previously donated this reservation.
At the time, seating information was not available, so we set the seat property to nil.
Now, the user has selected a seat, so we are going to donate the updated reservation details with the seating information set.
Keep in mind that the item reference must remain the same throughout the reservation life cycle.
Once donated, Siri will propagate this information to all the relevant places, including Calendar.
Next, let's talk about cancellations.
Cancellations are a special type of modification.
In this example, we already donated this reservation with a status that confirmed.
Unfortunately, the user had to cancel the reservation.
So we are going to donate the updated reservation details with a status set to cancel.
Like with all modifications, the itemReference must remain the same.
So, that's how your app should handle some of the things that can happen during the reservation life cycle.
Now, let's summarize what we talked about today.
So, we've seen how easy it is to take advantage of the Siri Event Suggestions API, and how we provide a great user experience throughout the reservation life cycle.
Here are the three main takeaways.
Your app should donate reservation details when they are displayed to the user, or when they are received in the background.
Make sure you keep your users up to date by donating when the reservation details change.
And finally, remember to handle app launch, so the users can get back into your app at the right time, and the right place.
For more information, and to get access to our sample code, you can visit our session link on the Developer Portal.
We also have some related sessions from previous years that we encourage you to check out.
Thank you, and I hope you had a great conference.
[ Applause ]