iOS 13 and Xcode 11 Changes That Affect Push Notifications
Over the last few months, OneSignal has tracked progress on the launch of iOS 13 to understand how it might impact our 700,000+ users. We discovered several technical changes to notifications in iOS 13 and Xcode 11, which have not been well-publicized by Apple.
If you already use OneSignal, you're in luck - we updated our SDK so your notifications will continue to work when iOS 13 comes out on September 19th. We also notified customers to make sure they're using the latest OneSignal SDK when they update their apps.
But what about developers who aren't using OneSignal to send push notifications? Maybe it's time to switch to OneSignal, where you can send push notifications to an unlimited number of mobile subscribers.
Below, is everything you need to know about Xcode 11 and iOS 13. The goal of this article is to help developers who don't yet use OneSignal.
Push Token Retrieval Changes
Starting in Xcode 11, the description
attribute of the deviceToken data sent to the push token delegate in iOS changed to a different format.
Many existing applications and software libraries use this attribute to fetch the push token by accessing the description
variable on the deviceToken NSData
instance, and then trimming certain characters from it to get the device push token, like so:
[[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; // This is now incorrect
If you're not a OneSignal customer, and you're not sure if you're affected – you probably are! Thousands of books, online tutorials, popular open source libraries, and StackOverflow answers have this, now incorrect, implementation.
If you are a OneSignal customer, we've updated all of our SDKs. Please make sure you are using the newest OneSignal SDK when you next update your iOS app. No steps are required besides simply using the newest OneSignal SDK.
The newly correct implementation is slightly more complicated but required to ensure that a consistently correct value is returned for iOS 13 as well as older iOS versions.
For those who don't yet use OneSignal, here is the copy of an implementation that works in Xcode 11+, while also being backwards-compatible. This change has already been made in OneSignal's SDKs:
+ (NSString *)stringFromDeviceToken:(NSData *)deviceToken {
NSUInteger length = deviceToken.length;
if (length == 0) {
return nil;
}
const unsigned char *buffer = deviceToken.bytes;
NSMutableString *hexString = [NSMutableString stringWithCapacity:(length * 2)];
for (int i = 0; i < length; ++i) {
[hexString appendFormat:@"%02x", buffer[i]];
}
return [hexString copy];
}
Fortunately, we became aware of this change early in our testing of Xcode 11 Beta and after receiving customer feedback about this issue. This gave us time to update all of our SDKs and notify affected customers.
A new attribute is required on all APNS (Apple Push Notification Service) API headers.
Apple recently added a new attribute to the headers for APNS Payloads: apns-push-type
.
Per Apple’s documentation, the value of this header must be set to "alert
" or "background
", based on whether the notification has user-visible content or not.
According to Apple, this header is:
“required when delivering notifications to devices running iOS 13”. Furthermore “if the header is missing on required systems, APNs may delay the delivery of the notification or drop it altogether.”
Our findings have been that many vendors and many open-source libraries have not yet made this change. Without this, apps may find some of their notifications being unexpectedly ignored by devices. OneSignal automatically sets the new apns-push-type
header to the right value for our customers.
APNS Priority must be set to 5 for background notifications
Many notification delivery systems set the apns-priority
header value to 10 (immediate delivery). Or, if this header is omitted, a value of 10 is the default assumed by Apple.
The other possible value of the apns-priority
header is 5
. This lower value reduces battery usage, but may result in the notification being delayed.
In a 2019 WWDC session, Apple said that a value of 5 is now required for all “content-available” notifications. These are notifications that may not contain user-visible data, but are used to invoke the app in the background to download updated content, such as recently received messages. Omitting this may cause the app to not launch.
Apple's documentation has some ambiguity on this field. Some Apple documentation pages indicate that apns-priority
must be set to 5
for all push payloads that have content-available
set to 1
(true). Other documentation pages indicate that content-available
can be set to 1
and apns-priority
can still be set to 10
, as long as the push message has content to be shown to the user (via the alert
field of the APNS payload).
Our findings are that the latter is true: At this time, apns-priorty
only needs to be set to 5
for notifications without any alert
data. OneSignal automatically sets this header to the right value for our customers.
Apple has started discontinuing support of TLS v1 for their Push API
For a long time, Apple has allowed connections to their push APIs via the very old TLS v1 protocol. Given this, many developers may unknowingly be using TLS v1 to send notifications.
If you're one of these developers, your notifications will stop working soon. This change was explained in response to several developers complaining of notification issues on Apple’s developer forums.
Our team has already ensured that we are using the most up to date protocol to connect to Apple’s HTTP/2 notification APIs in our backend, so OneSignal customers will not be affected in any way.
VoIP Changes
Apple supports a special type of VoIP (Voice over IP) push permission for some applications. This API was designed for apps that receive voice or video calls, such as Facebook Messenger or Skype.
Developers found that this special push type also had a few other valuable use-cases, including:
- Applications that were swiped-away from the task switcher could still receive background data notifications. Normally background notifications are ignored if a user closed an app in this method.
- Applications were using this API in order to support receiving encrypted background messages. They would then decrypt the message client side, and then show a local notification.
- Some apps were using this to periodically trigger their app to run code in the background, such as to reliably synchronize data so the user could view it while offline.
Apple recently changed this permission to require displaying a notification or incoming VoIP call to the user. As a result, VoIP notifications can no longer be used for the three above use-cases, or any other use case that's not related to receiving a VoIP call.
Instead, Apple recommends implementing many of the above use-cases by using either content-available
background notifications, or for the decryption use-case, Apple recommends using a Notification Service Extension. Apple is also introducing a new background tasks framework for cases where apps may need to schedule tasks to happen in the future. These changes, and recommendations on how to handle them, are outlined in Apple's recent WWDC presentation on privacy changes in iOS 13.
How to stay informed
It can be difficult to keep track of all the changes Apple and other companies make to their push notification implementations.
The OneSignal team stays informed of Apple's changes by carefully watching all relevant WWDC sessions, regularly reviewing Apple's documentation for changes, testing all Xcode and iOS beta releases, reading Apple's developer forums, and working closely with our clients.
All of this can be time consuming, but we pride ourselves in helping our customers stay ahead of the curve. Follow our Twitter or sign up for OneSignal to receive regular updates from us.