[ Music ]
[ Applause ]
Good afternoon and welcome everybody to our session, what's new in user notifications.
I'm Kritarth Jain [inaudible] on the iOS notifications team, and we're very excited to be back at WWDC to share with you all the new and exciting features around user notifications that your applications can start using with iOS 12.
Today, we will be going over a range of topics as you can see from the list here.
We will start with talking about grouped notifications, a new paradigm that we've introduced to iOS notifications when presented in the user's notification list.
Then we'll talk about notification content extensions, which are existing extension points with notifications, and discuss new APIs that you've added around these.
Then, we'll cover notification management and talk about all the new ways in which your application users can now tweak your notification settings and what you need to do to respond to these new options.
Then, we'll cover provisional authorization, which allows your applications to have a trial phase for sending notifications to users without their explicit permission but do it quietly.
And lastly, we'll cover critical alerts, which allows your applications to send important notifications to the users, which bypass certain system settings if your users allows your applications to do so.
So there's a range of topics to be covered today, and let's begin with looking at grouped notifications.
Now up to iOS 11, all new incoming notifications for the users were inserted in a chronological order in the notification list.
So these would be interspersed across multiple applications, and it would be hard for the user to find a certain notification or triage multiple notifications together.
So starting in iOS 12, we've decided to improve this by introducing notification grouping, so now, as you can see here, all notifications across different applications get grouped into their unique groups.
Let's take a deeper look at how grouped notifications works.
Now all these notifications will be automatically grouped, so there's nothing explicit that you need to do to start using notification grouping.
However, if you do want to have your own custom groups then you can use the thread identifier, which is an existing property on the UN notification content object.
So some of you might already be using the thread identifier and for a local notification.
You can set it on the UNMutableNotificationContent object as seen here.
And for a remote notification payload, you can also include it as part of your notification payload.
Now the thread identifier might be familiar to some of you already.
We use it today for forwarding notifications to a notification content extension that is presented for your application, which has the exact same thread identifier, allowing the content extension view to update it based on the new incoming notification.
Starting in iOS 11, we started using the thread identifier for doing grouping of notifications, if the user had turned on [inaudible] notification previous.
So we're just taking this concept and expanding it for all notifications in general.
So how does this grouping work?
So when a new notification comes in to you, the user's device, if there is no thread identifier set on this notification, then this notifications gets grouped with the application bundle.
We can see that from our sample application here, that as new notifications are incoming, they are getting bundled with the same group and the group is getting updated with the latest content.
And then the user can simply expand this notification group to see all the notifications that are present in that group.
On the other hand, if the notification does have a thread identifier set on it, then it gets grouped with all the other notifications from that same application with that exact same thread ID.
What this also means is that the same application can then have multiple different custom groups, depending upon the unique thread identifiers that you're setting on them.
A good example of this is the messages application, where here you can see there are two different threads, and as new notifications are incoming, they are going to their own respective groups.
And then the user can expand a specific group to see all the notifications that are part of that group.
So by using the thread identifier, messages is able to do so.
Now, your application users also have the option of tweaking this notification grouping setting from your per application notification setting's page.
Here, they get three options.
If they choose automatic, then they get the behavior that we just described.
However, the user also has the option of just grouping by application, where the system will ignore your thread identifier and group all notifications into a single group.
And if the user wants the same behavior as it exists in iOS 11 today, then they can simply turn off grouping for your applications' notifications.
So do keep this in mind when you're creating your own custom groups that they create enough value for users when they receive your applications' notifications.
Now what are the different components of a notification group?
The content that we show is for the latest notification that was received as part of that group.
And then the user can simply see all the notifications by tapping on this group, and we expand all the notifications' content.
And then the user can interact with all these notifications individually as well.
The two buttons at the top give the users much greater control like collapsing the stack as well as clearing all these notifications together.
Now, notification grouping also makes triaging of notifications much better.
For example, in this case, the user can clear all these notifications together by simply swiping to the right and tapping clear all.
Apart from the content of the notification group, we also show a summary text.
Now, this summary text, by default, shows the count of all the notifications that are part of that group.
However, you can also create a custom summary text so you can give your users much better context of what kind of information is included in that group.
Now, we will cover this API and go over much larger use cases of how you can create your custom groups in the advanced session around using group notifications, which will follow this session.
So let's do a quick summary of group notifications as we saw them today.
Starting in iOS 12, all application notifications are going to be grouped automatically.
You can start using the thread identifier if you want to create your own custom groups for your applications, but the user does have the option of changing this grouping setting for your applications' notifications.
And lastly, you can use the summary text for customizing the information you want to provide the user around the notification groups that you're creating.
All right, so that was group notifications.
Now, let's move on to the next topic and talk about notification content extensions.
Now, some of you might already be familiar with these content extensions that we included with iOS 10.
Content extensions allow your applications to present a rich notification view around the user's notifications, so you can have a much more customized and interactive interface for the notification that the user is seeing.
Let's do a quick recap of setting up these content extensions.
Xcode gives you a standard template to add a target for the content extensions to your applications and once you set that up, we create a default class for the notification view controller, which implements the UNNotificationContentExtension protocol.
Here, the did receive notification method is important because this is your entry point for setting up the view associated with the content extension, and you can use the notification object past here to get all the information around that notification to set up your custom view.
The info.plist file associated with your content extension gives you more options.
The important thing here is the category identifier.
Now, this identifier needs to match the same category identifier you're setting on your notification requests because that's how the system knows which content extension to launch with which notification.
Along with this, you can do some quick configurations of your content extension such as setting the initial content size ratio, hiding the default content, as well as overriding the title of this content extension.
Now, the primary way in which your users interact with these content extensions is through notification actions, and these actions are presented right below the content of the content extension.
Let's summarize how we can set up these actions as well.
So doing so is fairly trivial in code.
For example, here, we have two actions here for like and comment, and we create a simple UNNotificationAction for like and a text input action for commenting.
And once we've created these actions, we create a new category giving it the same identifier as the content extension where we want these actions to be presented.
And then, we pass it, the two new actions that we created.
Once we've set up this category, then we call setNotificationCategories on the UNNotificationCenter object associated with our class, giving it the new category that we created.
So by simply doing so, the next time when the user goes to your content extension we can see that these actions are now available for them to interact with your notification content.
Now let's take a look at how we can handle the responses from these actions.
There are two ways to do that.
Firstly, you can handle this response in the AppDelegate that is associated with your application that implements the UNUserNotificationCenter Delegate protocol.
Here, the function UserNotificationCenter did receive response, includes the response object which includes information about the request, the notification request from which the user took this action.
However, the content extension also allows you to intercept this action response so that you can update your view and make a much more interactive and dynamic experience for users for the content extension.
So for our sample here, we enter the did receive response method and checked the action identifier for the like action.
And then we update our UI with the new label as well as update our application state.
Finally calling the completion block we do not dismiss.
If you do want to dismiss your content extension view here, then you can simply change the parameter you're passing to the completion block to dismiss or dismiss and forward, where we will forward this response to your AppDelegate function as well.
All right, so now that we set this up, we can see that when the user takes the like action, the content extension content gets updated right there and then.
So it's a much more interactive experience for your user and they're getting real-time feedback.
However, if you look at the current state of the content extension, we see that there is some redundant information.
The user has already taken the like action, so having the action there doesn't really serve a purpose anymore.
Now notification actions, in general, have certain limitations.
They are not very dynamic and can't be updated based on the context of your content extensions.
Also, these tend to be tied to the notification categories that you have to define at the time of your application setup.
So we wanted to address these issues and we have introduced a new API around notification actions, where now we're exposing these notification actions as part of the NSExtensionContext tied to your content extension.
What this API allows you to do is access the currently presented notification actions to the user as well as replace these actions by setting a brand new array of notification actions for your content extension.
So going back to our sample, what if after the user took the like action we wanted to replace it say with the unlike action so that they can do the reverse of the action they just took?
So using this new API, let's take a look of how we can set this up.
So we go back to our did receive response method and again identify the like action and update our application state.
This time, we also create a new action for unlike, giving it a unique identifier as well as a title.
We can also take a look at the currently presented actions so that we can extract the comment action from there without having to create it again.
Then we create a new array of these new actions that we've created and simply set that on the notification actions variable.
So once we've done this and the user takes the like action, then the UI will automatically update to show them the new action, and then the user can then toggle between the two actions, depending upon how you handle that state in your content extensions.
Now, this API can be used in multiple other ways as well.
For example, now you can set your actions at the time you're setting up your content extension view in the did receive notification method.
What this means is your notification requests are no longer tied to the category to define the actions that you want to present around these notifications.
You can also now present a secondary set of actions by replacing the currently presented actions.
For example, if the leading action was rate, then you can provide a secondary list of the different types of ratings that you want your user to take.
And you can also remove all these notification actions if you feel it does not make sense anymore for your content extension to present these actions.
So that's the new API around notification actions.
And we feel this will really help you enhance the experience that your users have around your content extensions with the different actions now you can present to them.
Let's move on and talk about user interaction with these content extensions.
Now notification actions were important up till this point because till iOS 11 we did not allow user interaction touches with your content extension view.
Now we received a lot of feedback around this.
And I'm happy to announce that we're taking away this restriction with iOS 12.
[ Applause ]
So now your content extensions have the option of opting in to receiving user interaction [inaudible] touches, and setting this up, it's fairly trivial.
All you have to do is add a new key value option to your info.plist file.
And the key that we've added is the UNNotificationExtensionUser InteractionEnabled.
So going back to our sample, what if we want to remove the like action from a notification action and make it a UI interaction touch that's part of the view itself?
So once we've configured our info.plist file, we can go back to our content extension view and create our own custom button to handle the like gesture.
We add a target for our own private method and inside that function, we update the UI as well as update our application state.
So here, it's important that since you're implementing your own user interactions that you are responsible for handling all these actions, responses, and callbacks from the users yourself.
So once we've set this up, now when the user goes to your content extension we see the Like button, part of the UI itself, and the user can simply interact with that button right there and then.
So that's the new functionality that we've added around content extensions.
And coupled with notification actions, along with user interaction touches, you now have a much richer set of tools for creating much more interactive and dynamic content extension experiences for your applications notifications users.
Now let's talk about launching your application from the notification content extension.
So today the user can launch your application if touches were not allowed by simply tapping the content extension view.
They could also do so by tapping your application icon in the top left corner.
Or you could create a foreground action, which then would in turn launch the application.
But what if you wanted to do this from your own custom control?
What if you wanted to launch the application programmatically?
To enable this, there is a new API on the NSExtensionContext called performNotification DefaultAction, which would allow you to do this now.
Now, what does the default action mean?
So, as we said, it launches the application, but at the same time, it calls the UserNotificationCenter did receive response method in your application delegate.
Now the UNNotificationResponse object contains the information of the notification from which the user came, so you can update your application state based on the notification.
And the identifier that's passed here is the UNNotificationDefault ActionIdentifier.
So going back to our sample, let's see how we can set this custom control up.
Now again, we create our own UI button for the all comments and then tie it up with our own private function.
And in that function, we're simply calling PerformNotification DefaultAction.
So by simply doing that, you get this functionality to call this method programmatically from anywhere in your content extension code.
So that was launching the application.
What about dismissing the content extension view?
Again, let's take a look at how the user can do that today.
They can do that by tapping the Dismiss Button in the top right corner, or you can create your own custom notification action, which would in turn dismiss the content extension view.
Which you can set up, as we saw before, by passing dismiss to the completion block.
But again, what if we want to dismiss the view through our own custom buttons, and we want to do this programmatically?
Say that when the user taps the Like button, then the view dismisses because we feel the user's done interacting with the content extension.
To enable this as well, there's a new API called dismissNotificationContent Extension that's on the NSExtensionContext.
We go back to how we set up our Like button, and now this time, we also call the new function that we added for dismissing the content extension view.
And once we set this up, now when the user takes the like action, the view of the content extension gets dismissed.
Now one thing to note here.
That calling this method does not withdraw the notification that was posted to the user.
If you want to do that then use the existing API for removing delivered notifications with identifiers to get that functionality.
All right, now let's summarize all the new APIs that we've looked at today around the notification content extensions.
We started with talking about notification actions where now you can access these notification actions as well as replace them dynamically from anywhere in your content extension code.
You can now opt in to having user interaction based on touches within your content extension views.
You can programmatically launch the application from anywhere in your content extension code as well as dismiss the content extension view, depending upon where you feel it serves best your user's experience around the content extensions.
So that's a varied list of APIs around content extensions, and we hope this really helps you enhance your user's experience around your content extensions and then you start using these APIs.
So that was notification content extensions.
Now, the next topic today we're going to look at is notification management, and to tell you all about that, let me invite my colleague Teja to the stage.
[ Applause ]
Thank you Kritarth.
My name is Teja Kondapalli, and I'm also an engineer on the iOS Notifications' Team.
And, of course, I'm here to talk to you about a couple of the new APIs that we have.
The first of which is notification management.
But before I dive into this API, I want to cover some of the user facing features to give you some more context and then we can deep dive into the API.
As our users get more and more apps on their phones, notifications become the primary way that they interact with these apps.
But often, they find themselves in a situation like this.
With far too many notifications.
And it becomes hard to sift through and find the important ones.
So perhaps to make this easier, this user has decided that notifications from podcasts don't need to be shown on the locked screen.
Right now to configure that they'd have to launch the settings app, find notifications, find the podcast app, and then they can configure their settings.
We wanted to make this easier.
So, in iOS 12, we're introducing a new management view where the users can configure their notification settings directly from the notification without having to launch the settings app.
There's three really easy ways to get into this management view.
The first is what we just saw.
You simply swipe over a notification, tap manage, and the management view comes up.
The second is if you can go into the rich notification, you can tap in the right corner, and you can also launch the management view.
And the third is actually in the list itself.
Depending on how your users are interacting with their notifications, they will occasionally see suggestions, like this one, that ask them if they want to keep receiving podcast notifications.
And from here, as well, they can tap manage and bring up the management view.
Let's take a closer look at the management view.
And we obviously have options here where users can configure their notification settings directly from this view.
But if they want to go into the settings app and configure in a more detailed manner, they have a quick link to the settings for this application, the notification settings.
A And also from this view, they have some actions they can take directly, the first of which says deliver quietly, which is probably a concept that's new to all of you.
Some of these management views will also have an option that says deliver prominently, so let's talk about what this means.
In iOS, we have a lot of settings that users can configure, and this is really great for the power user.
The can customize their settings to every detail, but for the regular user, we think that we can help them out by categorizing their notification settings into two big categories.
Notifications that are delivered prominently and notifications that are delivered quietly.
Notifications that are delivered prominently are what we're used to.
They show up on the locked screen.
They show up in notification center.
They roll down as banners.
They badge the AP icon and they can play a sound.
Notifications that are delivered quietly only show up in notification center and they don't play a sound.
And from the management view, in addition to configuring whether they want their notifications delivered prominently or quietly, users also have the option to turn off their notifications.
Now, I know that you might worry that your users are going to turn off the notifications for your app, so we've added this extra confirmation sheet just in case they do tap turn off.
And from here, they can also turn off their notifications.
But we've also added an API to add a second option to this confirmation sheet, and podcast has taken advantage of this API, so it says configure in podcast.
This is a link that will deep link within the podcast app to a custom settings view that allows the user more granular control about what kind of podcast notifications they want.
And as your apps send more and more notifications and various type of notifications, we think it's really important to allow them this granular level of control over what kind of notifications are important to them.
This link can also be accessed from the systems settings app from your apps' notification settings.
And you can see for podcasts it's right at the bottom.
It says podcast notifications settings.
Let's see how we do this in code.
In the class that conforms to UNUserNotificationCenter Delegate, we have a new delegate method.
Open settings for notification, and as long as you implement this delegate method, those links that we talked about from the management view, or from the settings app, will automatically be populated by the system for you.
So when the user taps on any of these links, this delegate method will be called.
And it's really important when this delegate method is called that you immediately take your users into the view where they can configure their notification settings within your app.
And if you notice, we have [inaudible] parameter to this method, and it is notification.
So depending on where the link was tapped from, if it was tapped from one of the management views, it will have the value of the notification that that management view came from.
If it was tapped from the settings app, the value of notification will be nil, and you can use this information to show the appropriate notification settings when this delegate method is called.
So that's what we have for notification management.
It's a new way for your users to configure whether they want their notifications delivered prominently or quietly, or turn them off, or even configure them at a granular level within your app.
And to encourage your users to keep getting your notifications delivered, we think it's really important that you make the content in the notifications relevant.
We also encourage you to use thread identifiers to group the notifications when you think it's appropriate.
This will help the users organize their lists better and will make sure that they're not overwhelmed by the notifications from your app.
We also think that as your apps send various types of notifications, it's really important to provide that custom settings view within that app so that users have more granular control about what kind of notifications are important to them.
That's what we have for notification management.
And the next big feature I want to talk to you about is provisional authorization.
Right now, when a user installs your app, before they start receiving notifications, at some point they'll have to respond to a prompt that looks like this, which is asking them if they want these notifications.
And the biggest problem with this is, at this point, the user doesn't know what kind of notifications this app is going to send, so they don't know if they want them or not.
So, in iOS 12, we're introducing provisional authorization, and this is an automatic trial of the notifications from your app.
This will help your users make a more informed decision on whether they want these notifications or not.
So you can opt into this, and if you do, your users will not get that authorization prompt that we just saw.
Instead, the notifications from your app will automatically start getting delivered.
But these notifications will be delivered quietly, and if we recall, notifications that are delivered quietly only show up in notifications center, and they don't play a sound.
Notifications that are delivered with provisional authorization will have a prompt like this on the notification itself.
And this will help the users decide after having received a few notifications whether they want to keep getting these notifications or whether they want to turn them off.
And this turn off confirmation sheet will also have the custom settings link if you have provided it.
Let's see how you can do this in code.
In the location where you regularly request authorization, in addition to whatever options you might be requesting, you can add a dot qualifying option called .provisional.
And if you include this, you will automatically start participating in the trial.
It's really important to note that the .provisional option is in addition to whatever other options you may be providing.
That's because if the users decide to keep getting your notifications delivered, we want to know how you want them delivered, with badges or sounds or as alerts.
So that's what provisional authorization is.
It's an automatic trial of the notifications from your app to help your users make a more informed decision about whether they want these notifications.
And again, to encourage your users to keep getting your notifications delivered, it's really important to make the content in your notifications relevant.
And also, it's really important to use .provisional as a qualifier option in addition to whatever other options you're requesting.
That's what we have for provisional authorization.
And the last big feature that I want to talk to you about are critical alerts.
Often when I'm in the middle of a meeting or attending something important, my phone looks like this.
And as you can see, I have do not disturb turned on.
Or at least I have the ringer switch turned off so that I don't hear any sounds when I get notifications.
And usually this is really good, but I would have missed a really important notification like this one.
This is a health-related notification.
That's from a glucose monitor that's warning me of low blood sugar, and this is something I would want to see immediately.
Scenarios like this made us realize that we need a new type of notification, and this is what we call critical alerts.
Critical alerts are medical- and health-related notifications.
Or home- and security-related notifications.
Or public safety notifications.
And the key to a critical alert is that it requires the user to take action immediately.
The way that critical alerts behave is that they bypass both do not disturb and the ringer switch, and they will play a sound.
And they can even play a custom sound.
But what that means is that these are very disruptive, and for that reason we don't think that all apps should be able to send critical notifications.
So in order to start sending a critical alert, you will need to apply for entitlement, and you can do that on the developer.apple website.
This is what a critical alert looks like, and you can see that it has a unique icon indicating that it's critical.
And it would have also come in with a sound.
Critical alerts also have their own section in notifications settings.
This means that a user can choose to allow critical alerts for a particular application but choose not to allow any other type of notification.
And before users start receiving critical alerts, they will have to accept a prompt that looks like this that's asking them specifically whether they want to accept critical alerts from a particular application.
So, of course, in order to start sending critical alerts, you'll have to request authorization.
So after you apply for entitlement and get it, in the place where you regularly request authorization, in addition to whatever other options you want to request, you can also request a .criticalAlert option.
And this will give your users the prompt.
And let's see how it actually set up and send a critical alert.
It actually behaves very similarly to a regular notification.
You can see that I just set up a notification with the title body and category identifier, but what distinguishes this as a critical alert is that it plays a sound.
So I need to set a critical alert sound.
And here, you can see that I'm setting the default critical alert sound that's provided by the framework.
I can also set a custom sound.
And I can also set a custom audio volume level.
And of course, critical alerts can also be push notifications so all of this information can be set in the push payload as well.
So that's what we have for critical alerts.
They're a new type of notification that requires the users to take action immediately.
And they're very disruptive, so you need entitlement to be able to send them.
So that's all the new exciting APIs that we have for you today.
I just want to quickly go over all the things that we covered.
We talked about how you can use thread identifiers to group your notifications to help your users organize their notification lists better.
We talked about all the great new APIs around notification content extensions, which will help you make your rich notifications much more interactive.
We talked about how you can provide a custom settings view within your app to allow your users more granular control over what kind of notifications they want to receive.
We also talked about provisional authorizations, which is an automatic trial of the notifications from your app, which will help you users make a more informed decision about whether they want these notifications or not.
And last, we talked about critical alerts, which are a new type of notification that requires the user to take action immediately and that are disruptive.
So we hope you take advantage of all of these great APIs and make the notification experience for your users even better.
You can find all the information about this session on our sessions' page at developer.apple.com.
We're session 710.
We have another session just following this one in hall three called using grouped notification where we'll help you determine how to best group notifications for your app.
We have two notifications labs, one today and one tomorrow, where you can come and ask the engineers on our team any questions that you may have.
And on Friday morning, we have an interesting session called designing notifications.
That's going to be hosted by the designers who helped us come up with the designs for these, and they'll be talking about notification best practices.
Thank you and have a great dot dot.
[ Applause ]