[ Applause ]
Good afternoon everyone.
I'm Sirisha from SiriKit Engineering.
I'm joined by my colleague and friend Tin to talk about all the cool new features we are bringing this year in SiriKit.
SiriKit was introduced last year, a brand new way for everyone to do things in their apps using their voice.
The main goal of the release was to make sure to give you the ability so your services and content can be integrated with our SiriKit so users can now talk to their apps using Siri.
To make this happen, we've opened up numerous domains like Workouts, Messages, Ride Booking, just to name a few.
Every domain had one or more intents.
And intents had a specific task like the Messaging domain.
Users were able to send a message or search a message.
Ride Booking, everybody were able to book ride in their preferred apps.
Or paying bills in Payments domain.
Because of these intents, we gave you the ability to pick and choose the intents that you want to register that best suited your app capabilities.
In our release Watch 3.2 we started supporting SiriKit on watchOS platform.
By writing a Watch extension you were able to take all the advantages of SiriKit Intent framework on the Watch.
As our ongoing effort to make your experience seamless and easy, we've added our support to simulator.
Starting iOS 10.3 and watchOS 3.2, you were able to debug and test while writing SiriKit extension.
This is a big year for us.
Great reception and amazing feedback made this happen.
Let's take a sneak peek about all the cool things we are bringing this year.
A lot of new domains and many more intents.
Brand new APIs to give you move control to customize the feel and look at your apps view in Siri.
And lots of enhancements to our systems and APIs for a much improved user experience.
So, let's talk through the domains first.
We've added new intents to our Payments domain.
We've add our support to Lists and Notes functionality.
If your app uses visual codes, you can start integrating with SiriKit starting this fall.
Payments was introduced in iOS 10.
When we introduced, we added our support to sending money and requesting money.
In our 10.3 release we've added the support for bills.
Users were able to search for bills and pay bills.
We are extending our support further this year by adding our support for accounts.
Users will now be able to transfer money from one account to another, or search for account information.
Let's take a look at these.
First I'm going to talk about the transfer intent.
If you look at the screen, Siri is very capable and powerful to understand such long requests.
For right now I'm just going to walk through line by line.
Transfer $10 tomorrow.
$10 will be mapped as amount.
And tomorrow is converted to the exact date.
Easy. The transaction properties are simple and map rightly.
What about accounts?
Accounts can be referred in many ways.
I sometimes like to use it just by organization name.
Or, like an account type like I've used here: checking, savings, credit.
Siri understands all times of accounts and makes sure that it infers rightly and then gives it to your app.
Well and good.
What is this Rainbow Savings?
This is the name I have used when registering my account in one of my apps.
And I want to make sure that Siri understands my account nicknames, too.
And how is this possible?
When you registered user-specific data using our IN Vocabulary API, we will be able to understand user's specific information.
You can look for more information of IN Vocabulary API in this link.
So, let's talk about Search.
Our second intent is a Search for Accounts intent, which will be able to list all the account types if the user just asks to list all the accounts.
Just enough information to distinguish between the accounts, along with the balance.
And if the user wants to know more about each account, they can just click on any of the item to get a detailed view.
Search for Accounts intent, not just shows all the accounts, but also can be used to query for specific account information.
What is the balance on my Rainbow Checking account?
I'm asking specifically my balance on a specific account.
And Siri perfectly understands it and then gives the user the required information.
We don't only support the normal balance, but also we've added a couple of balance types.
Like if your app supports airline mileages or reward points.
Siri can understand them as well.
How many miles do I have on my Sparkle card?
Siri understands it and then passes it to your app.
And thus giving the user the required information.
So, INTransferMoneyIntent can be used to transfer money from one account to another.
INSearchForAccountsIntent can be used to check balances, to list all the accounts or to check any specific account information.
That's all we have for Payments this year.
With our analysis, we found out that managing lists and notes is one of the very popular use cases in Siri users.
And so, this year we're extending our support to support lists and notes.
We've added all the APIs to make sure that users can create, edit, manage, their lists, notes, and reminders.
Not just that, but also users will be able to search in their lists and notes.
Let's take a look at them.
This is an example to create a list.
I can ask Siri to create a list by giving a title and also the contents.
And Siri is powerful enough to distinguish between them, understand them, and pass on the right information, filling in the intent, giving it to you to create the view.
This is one of my favorite intents: the joys of marking tasks done.
SetTaskAttributeIntent can be used for this.
This has a task type, which is completed, not completed.
And that carries the information between Siri and the app to make sure that we do the action correctly.
We've added brand new intent to support reminders.
We can create reminders in many ways.
Siri supports two types of reminders: spatial and temporal.
Let's talk about spatial first.
An example here: Remind me to leave work at 5 p.m. in UnicornNote.
I'm asking Siri to remind me to print slide when I get to work.
I'm making I want Siri to make sure that it understands the geolocation of the word and then pass on the information to you so you can create the right reminder for the geolocation.
The next example: Remind me to leave work at 5 p.m. This is to make sure that the date trigger is created.
If you look at both the examples, Siri is powerful enough to understand when I said "leave work at 5 p.m."
to create a date reminder, but not a location reminder for leaving work.
And in the before example, Siri created a location trigger when I said "arrive at work."
Siri is very powerful in parsing these use cases and understanding them to create the right intent and pass it over to you.
So, CreateTaskIntent can be used to create tasks, lists.
AddTasksIntent for the reminders and adding tasks to the existing ones.
SetTaskAttributeIntent to set a task or to mark it completed or to update it to a reminder.
Let's talk about the notes.
Notes can be created in many ways.
I can create by using the title, the content and even under a folder.
And Siri supports all these options.
So when I ask Siri to create a note with just given title, it just creates a blank note.
I can also ask Siri to create a note under a specific folder along with its content.
Siri parses the whole user intent and then maps the appropriate title, group name, and content into the intent and then pass it over to you to create the right note.
And adding to an existing note.
This is possible with Siri, too.
Here, Siri understands the target note as WWDC.
And then the actual content.
And then passes the information over to you to create the note.
Let's take a look at the intents.
CreateNoteIntent to create brand new notes.
AppendToNoteIntent to add to an existing one.
The next big intent in the Lists and Notes is Search.
When you get asked to just show all the information, Siri understands and then passes the intent to your app.
And Siri lists all the notes, lists, reminder, passed on by the app to us.
We can display as is if you want us to.
Or, you also have the option of mentioning it to be sorted by date, where Siri will go ahead and sort all the items by date.
And then show it to the user.
Not just showing all the items, but user can also query using a specific type, like show just the notes or just the lists.
Or show the notes I created yesterday.
Or even show my completed tasks.
There are many types we support under this intent.
And the intent itself is called SearchForNotebookItemIntent.
And it supports all these types.
So user can ask if using any one of these and Siri will understand perfectly and thus completing the action.
And that's all the Notes and Lists new APIs we have.
Visual codes like QR codes, Bar Codes, are becoming very popular these days.
They're being used in numerous ways in the apps.
Like they're used to just open a web page instead of typing a tedious URL, especially they're in foreign languages.
Just showing a QR code opens a web page.
Or using them to send payment or request payment just by showing a code.
Paying at a gas station or paying to friends.
Apps are using bar codes to perform specific tasks.
And not just bar codes or QR codes.
We are also having codes as contacts in networking apps to connect to each other instead of going finding a person and then connecting.
By just showing a contact code, we are able to connect easily.
And starting iOS 11 Siri will be supporting visual codes.
Users will now be able to say "Show my UnicornChat code," which means Siri understands that this is a visual code intent, and then pass on the information to your app.
Whereas if the code could we support different types of codes, depending upon what app gives us, we share it back to the user.
And the intent that can be used to this functionality is INGetVisualCodeIntent.
It has one property type, visualCodeType, which supports it could be a contact or a request payment or send payment.
By registering to this intent users will be able to ask Siri to show the visual codes of any of these types in their favorite apps.
Now I invite my colleague and friend Tin over to show you this in action.
[ Applause ]
Thank you Sirisha.
My name is Tim.
And I'm engineer on the Siri Client Team.
So last year at WWDC we introduced an app called UnicornChat.
It was great.
Let our unicorn friends, like Celestra here, send messages to Sparkle Sparkly.
And it was great.
This year we want to add the brand new Visual Code Intent support to the app.
And it's super simple.
So the first thing we want to do is we want to make sure to modify our info.plist.
If your app hasn't yet adopted SiriKit, all you need to do is to go and create in it IntentsExtensionTarget in your project, and you'll have the info.plist, which you can edit.
Once you have it, go ahead and add under the Intents Support Key the new visuaCodeIntent.
The next thing that's important to notice is your principal class.
The principal class is where Siri will call into your app and ask you to begin handling your intent.
And that's where we're going to begin modifying our application.
I'm also going to modify the intents extension scheme and fill out this field Siri Intent Query.
I can prepopulate it with text to show my UnicornChat code.
This way every single time I build and run, Siri will prepopulate that text.
I don't need to speak to it every single time.
This will make debugging and development much faster.
Let's code now.
[ Applause ]
Let's take a look at the demo.
So here I am in my principal class of my intents extension for UnicornChat.
And we're already hailing the SendMessageIntent.
So let's go ahead now and handle that VisualCodeIntent.
It's pretty easy.
If you're handling multiple intents within your application, it's a great idea to split them up across multiple classes.
This separates your logic and makes things easier to test and debug.
So let's go now into our VisualCodeIntentHandler class.
As a reminder, you need to do three things when you're handling a SiriKit intent.
The first thing you want to do is to resolve your intent.
Resolving gives you an opportunity to customize Siri's properties and how it handles the properties of the intent.
Second, is Confirm.
Confirm gives you the place to tell Siri a ready signal, that you're ready to handle the intent, as well as do validation.
Finally, you'll just go ahead and handle your intent.
For this VisualCodeIntent, we'll return an image and tell Siri to display it.
So let's go ahead and get started.
I'll make my class conform to the INGetVisualCodeIntent handling protocol.
And the compiler's telling me I need to implement some required methods.
Go ahead and do that.
So the only required method is the Handle method.
But we strongly recommend you implement both Resolve and Confirm.
This is going to give you the most control and customization over your user's behavior within Siri.
I'm going to move this out of the way for now.
And we'll implement Resolve first.
Again, resolution is where you customize your behavior for Siri's properties of the intent.
For the VisualCodeIntent, there's only one property, and that's the VisualCodeType.
As Sirisha mentioned, it could be a contact code, a payment request code, payment send code.
So let's implement our custom logic now.
Here, if the user asks for a contact code, we'll tell Siri we're going to handle it successfully as a contact code type.
If the user doesn't specify which kind of code they want, like they say "Show my code" using UnicornChat, Siri will populate the type as unknown.
And here we can customize the behavior and also tell Siri we want to handle that as a contact code type.
We won't support Payment Send or Payment Request in our demo app.
So we'll tell Siri it's unsupported.
And when we do so, if the user asks for a payment code, Siri will intelligently dial out to the user in all the languages that Siri supports.
We don't have to write a single line.
So that's the power of SiriKit.
Now we're done resolving the properties.
Let's go ahead and confirm this.
So confirmation, again, is where we give Siri that ready signal.
And it's a great place to do validation.
So we want to make sure that our Unicorn user has a valid and active account before we show that contact code.
If they do, we'll go ahead and return Ready response code to Siri.
But what happens if the user doesn't have a valid account?
Well, it'd be great to launch our app and be able to perhaps ask them to sign up or reactivate their account.
And we can do that using a custom user activity.
So we'll create a custom user activity with a custom user info dictionary with our error specified.
And we'll turn to Siri failureRequiringAppLaunch and pass the user activity.
Now, if the user asks for a code and they haven't signed up or their account's inactive, Siri will show an error and give the user an opportunity to launch the app.
And if they launch the app, the user activity is passed on to the app.
And then you can extract that information, ask them to sign up.
Make sure they can connect with their Unicorn friends.
So now we're done with Confirm.
Let's go and handle this.
Handle's very straightforward.
We're just going to return a success code to Siri in the response.
And we'll set the visual code image property on that response to be our contact code image.
So this looks pretty good.
Let's build and run now.
It's prepopulated my request.
And there we have it.
Our brand new visual code.
[ Applause ]
So let's switch back now to slides and recap.
So when supporting intents, all you need to do is remember to modify your info.plist.
Again, if you don't have an info.plist, just go ahead and create a new Intents Extension Target in your app and you can edit it.
Next, make sure to modify your principal class, handle that intent.
Finally, Resolve, Confirm and Handle your intent.
I'd like to switch gears a little bit and talk about customizing your UI within Siri.
As a reminder, there's two types of extensions in Siri.
The first type is the Intents Extension, which you just saw.
It's where you do your Resolve, Confirm, Handle, handle your business logic.
This is required.
The second type is an Intent UI extension where you can use to configure your view.
And this is what we're going to be talking about now.
So, in iOS 10, we let you customize parts of your view.
Here's a RequestWriteIntent.
And we allowed you to customize certain parts of the view like replacing the map with your own custom view here.
We really like unicorns here.
So, this was great.
It lets you show additional information, your own style.
But we noticed sometimes there are issues.
There's duplicate information, like this pickup location, drop off location are duplicated.
Same with the fare.
This is because you didn't have full control over all the visual elements within Siri.
Well, this year in iOS 11 we're going to give you that full control.
And in order to do that, I'm going to explain it to you a little bit how Siri draws its views.
Siri represents its views as a stacked series of UI elements, each of which is backed by data called a parameter.
So for example, the map is backed by a pickup location parameter, so on and so forth for the rest of their views.
The ride option name, drop off location and so on.
Here's another example.
Here Sparkle Sparkly is coming to pick us up in a majestic unicorn.
And he's represented by this view is represented by two parameters, a ride driver and a ride vehicle parameter.
So some views can be represented by multiple parameters or sets of parameters.
In iOS 11 we expose this as a new class called INParameter.
And this is a class representing that data.
So here's the pickup location INParameter.
It's constructed using a parameter class.
In this case the RequestRideIntent.
And then a key path which is a property a location to a property on that class.
So the parameter represents a sort of key to the value.
And we want to be able to get the actual value, too.
So there's a new method also on the INInteraction called parameterValue.
When you pass the parameter into the interaction, you'll get back the actual value.
For the pickup location, it would be a CL placemark object.
Different parameters will have different parameter value types.
For example, the price range parameter would have an INPriceRange type.
So, with this concept of parameters, we can go from giving you control over a single view to all of the views, customizing them for parameters.
And we'll walk through that now.
This is the principal class of the intents UI extension.
It conforms to INUIHostedViewControlling.
This is the same as before.
And our new method is called configureViewFor parameters.
So you'll be asked to configure your view for a set of parameters.
You'll be given an interaction object.
This will let you resolve those parameter values.
You'll be given a context.
This will tell you whether you're being drawn within maps or within Siri.
And then finally, you'll be given a completion block.
And you'll call this and it has three parameters.
The first is a Boolean.
You'll return True or False here.
True meaning you wish to draw a custom view for this set of parameters.
False means you want to let Siri draw its default view.
Second is the set of parameters that you're handling if you choose to return True.
Finally, you return a size for your view for Siri to draw.
Let's walk through a concrete example and show you how we can customize a Request Ride Interaction using parameters.
We'll make more unicorns.
So, on top is Siri.
Bottom is your Intents UIExtension.
You're first going to get called with an empty set of parameters.
This will give you a chance to draw additional information, handle parameters up front, and for this case in our example, will return False.
Meaning we want to let Siri draw the default view for this parameter.
And the default view for an empty set of parameters is actually no view.
This is how it looks like in code.
Now, Siri needs to keep calling configureView until it resolves all the parameters for the interaction.
So the next view or the next set of parameters is the pickup location.
So it's going to ask you to configure your view for this section.
This time we're going to turn True.
We're going to tell Siri we're going to handle that pickup location.
And then the size for our custom view.
When we do this, Siri will replace its default view with our custom view.
And it will remove all instances of the default view it would have drawn.
Finally, it will respect the size that we asked for.
So here's how it looks like in code.
We'll go ahead and define our pickup location parameter.
We configure our view when we're asked to configure for the pickup location.
And tell Siri True, and we're handling it.
And finally we'll move our False completion to an else block.
So Siri, again, is going to keep calling configureView until it resolves all the parameters.
Then next is the ride option name.
And not only can you tell Siri False, to let it draw a default view, or configure one parameter at a time, you can actually tell Siri you want to configure multiple parameters at a time.
Or all the rest of the parameters.
So here we're going to tell Siri we're going to handle the ride option name and then all the rest of the parameters in the view.
And Siri will place all those parameters with our custom view.
And Siri will no longer ask us to configure the view any further because we've told it we're handling the parameters.
Here's how it looks like in code.
We configure our parameters.
We've commented this part out.
Pick up location's just like before.
Here we're handling the ride option name and all the rest of the parameters.
And then our completion, False.
So we go from this view, which has duplicate methods to be able to control all of the views and all the parameters for those views.
And not only can we do this type of layout, we can do any type of custom layout we want.
We can draw some custom views.
We can have Siri draw the rest.
You can draw all custom views.
Have a custom header.
So, it's super powerful.
So let's take a look at this live in Xcode.
Customize our Unicorn Ride app.
We're going to use a pink theme.
Unicorns love pink.
And we're going to handle two views.
We're going to handle the fare and special pricing parameters on the top view.
And then pickup location, drop off location, ride option name on the bottom.
And again, I'll use the Siri Intent Query feature to prepopulate a request.
So let's take a look at a demo again.
So here I am in my principal class for my Intents UI Extension.
It conforms to the INUIHostedViewControlling protocol.
And let's go ahead and implement that new configureView method.
The first time around, I'll return False to every single thing.
So Siri is going to draw its default views for all the parameters.
We can also put brake points here during debugging to see which sets of parameters we're getting called for in which order for the interaction as well.
Let's build and run this.
We've got our default view here because we've told Siri False to all the parameters.
This isn't very Unicorny, so let's get started and make it more pink.
Let's take care of that fare and special pricing parameters.
So back in our controller.
We'll define parameters that we're handling, fare and special pricing.
We'll handle our parameters and then extract the real values for these parameters from the interaction object on that first call when Siri asks us to configure for an empty set of parameters.
Next, we'll take our parameter values, go ahead and use it to configure our Unicorn Ride View.
And then we'll tell Siri we're handling the custom view for these parameters, and then the size.
Go ahead and move this to an else block.
Let's build it around this.
And it's looking a lot better.
We got our pink view here handling the fare and special pricing.
And because we've returned False to the rest of the parameters, Siri's drawing the default views for pickup location, drop off location, ride option name.
So to fully customize our view, let's go ahead and take care of the rest of the parameters.
Here we're just defining the rest of our parameters, just like before.
Once again, we're configuring our view.
When Siri asks for the pickup location, extracting the real values using the parameterValue method for the interaction.
Finally we'll use those values, again, configure our Unicorn Ride View for these last parameters and tell Siri we're handling them with our custom size.
This looks pretty good.
So let's build and run this one now.
And now we've got our fully Unicorny custom ride view.
So that looks great.
[ Applause ]
Let's go back to the slides.
Just to recap, when configuring your view for parameters, know that you'll be called multiple times to configure your view.
You're first going to be called with an empty set of parameters.
So again, you can draw additional info, your own custom header.
Or you can even handle parameters up front here.
You'll be called in order for a set of parameters for a given interaction.
You'll be able to find the set of parameters in the order in an upcoming update to the documentation.
Finally, just go ahead and handle your parameters, return the size up to Siri and draw your view.
In an upcoming seed we're going to add a parameter to the configureView method called Interactive Behavior.
So certain views and certain parameters have interactivity associated with them.
So for example, the map, you can tap it, you'll get another view.
That's like a next view.
Certain views may launch your app.
So the Interactive Behavior parameter will give you hints about the type of interaction that's available for these parameters.
And you can use that to customize your view as well.
There will also be another method called Description of Interface Parameters on your Intents UIExtension Context, which you can use during debugging in order to printout the order of parameters and the set of parameters during a give interaction.
So, this is the brand new INInteraction API.
It's super powerful.
And we can't wait to see what you guys build with it.
I'm going to hand it back to Sirisha to talk about some additional enhancements.
[ Applause ]
Thank you, Tin.
Along with adding more domains and the powerful parameters Tin just introduced, we've spent a lot of time enhancing our systems and APIs.
I'm not going to go over all of them, but I want to talk about two of them.
First, I'll cover Background Workout App Intent Handling, an ability to start workout apps in background.
And Alternative App Names.
We'll get to it in a minute.
Workouts are very popular intents.
Users love to use Siri to control their workouts.
It's very easy.
The current implementation when user requests any action on a workout, Siri calls the extension.
And then the extension hands it over to the app.
And thus Siri asking permission for the user if the device is locked before launching the app.
We changed this a bit this year.
We wanted to make sure that before launching the app we launched the app instead of in the foreground, but in the background.
So users can now just talk to Siri and have the app launched.
And this is for the Workout Intents starting iOS 11.
Let's look in the code.
This is the current implementation.
A sample code for a start workout intent response.
The extension usually returns continuing app, which when Siri calls the application method in the UI application delegate, passing the NS userActivity, prompting an app launch.
We've added two new things to change the flow.
We have added a new intent response code Handle an App.
So, you have a choice to return Handle an App response code to make sure that we call a new application method.
We've added a new application method on the UI Application Delegate.
This takes IN Intent and a completion handler.
So, when you pass in Handle an App as an intent response code, and implement the new application method, we will call the new application method, prompting to launch the app in the background.
This is very useful when the users just want to start Workout or pause, even through airports.
They don't even have to touch the device.
Let's take a quick look at the flow.
How does this look?
User wants to start a workout.
We launch the extension, call the handle method.
And the extension returns the new intent response code, Handle an App.
And then Siri calls the application, the new application method, passing the IN Intent and the completion handler.
And that completion block inserts the intent response code.
And then application will be launched in the background and passing the success back to Siri with the completion of the activity.
We believe this will make user's experience more easy, more seamless while controlling their workouts.
And we're very excited for this.
The second enhancement I'm going to talk about today is alternative app names.
Usually user can actually call an app in different names, different varieties.
Like UnicornPay can be just called as Unicorn.
UnicornPay or CornPay.
We want to make sure that we understand all the variations of the app names the user uses and invoke the right app.
So, to make this happen, we've introduced a new field AlternativeAppName in the .plist.
While registering in the .plist you have the ability to fill in all the app names that you think a user might use to refer to your app.
There is a field called AlternativeAppNames which takes the actual names and then the pronunciation hint you can also fill in, if you think that's necessary.
This will help Siri understand all the variation of the app names and make sure to invoke and call the right app the user is expecting.
So far we've introduced new domains, Lists and Notes, and visual codes.
And new intents in our Payments domain to support accounts.
Brand new APIs to give you more control to customize the views.
My colleague Tin introduced this.
And finally, the enhancements like starting a workout app in the background and also giving you the ability to provide us all the alternative app names that you think a user can call.
Please visit our website developer.apple.com for more information under our session 214.
We have another session coming up, Making Great SiriKit Experiences, where our experts will talk about methodologies, techniques, helpful hints you can use while you're writing in Siri Extension.
Thank you all for joining us today.
We're very excited to see all the new things you're going to bring using our new APIs.
[ Applause ]