Build local push connectivity for restricted networks
Leverage local push connectivity and deliver notifications from your application server to devices on networks without an internet connection. Learn how to construct notifications for apps running in restricted network environments, helping people communicate with the same reliability and experience they would expect when connected to the internet. We'll explore the technical details for this technology, when you might want to use it, and how to implement it in your app.
Hello. Welcome to Build Local Push Connectivity for Restricted Networks.
My name is Paresh Sawant. I'm an engineer on the Internet Technologies team at Apple.
I'm going to talk about the new Local Push Connectivity API in iOS 14 Push notifications are great for keeping your app users informed with timely and relevant content. However, delivery of push notification relies on Apple's Push Notification Service, which is only available when devices have an internet connection.
We received feedback from some of you that the ability to receive messages from your application server is a critical part of your app's functionality and must continue to work even when there is no internet connection. To meet this requirement for your apps, we have added a new API in iOS 14 that allows you to create your own push connectivity service that works on Wi-Fi networks. I will start out with a recap of Apple push notifications. Then, I will talk about how to build a custom push notification service using the new API. Later, I will demo this new feature using the sample app, and then, I will head over to the details of using the new API. So, let's get started.
I'm sure many of you are familiar with push notifications. Many apps use push notifications for news alerts, sports updates, instant messaging, receiving VoIP calls, and many more. Let's review how it works. Your provider server sends a push notification request to the Apple Push Notification service, also known as APNs. APNs conveys corresponding notification payloads to each targeted device. On receipt of a notification, the system delivers the payload to the appropriate app on the device. Depending on the notification type, your app uses either PushKit or the UserNotifications framework to receive the payload.
APNs is the centerpiece of the push notification feature.
Push notifications is the right solution for your apps when used on networks that have APNs connectivity over the internet. It's very optimal since it implements a single connection between the device and APNs to deliver the notifications to all apps on the device.
Push notification offers the desired user experience in your apps, and most importantly, it is very energy efficient. So, developers should prefer either PushKit or the UserNotifications framework to handle notifications originated from their servers.
However, if your app is used in network environments where APNs cannot be reached, the app cannot receive these notifications. For example, places like cruise ships, airlines, camping sites, or hospitals may have limited or no APNs connectivity. The push notifications feature of your app can get impaired in such conditions.
Push notifications play a very important role in providing users with timely information and give them the ability to take appropriate actions in response.
So, it's very important to keep push notifications functional even in constrained network environments when it matters most to the users. Local Push Connectivity is a solution that is designed to solve this problem, and we have added the Local Push Connectivity API in iOS 14. This is a new member in the NetworkExtension family of APIs. Let's see how it works. With the help of this new API, you can build an app extension that can directly communicate with your provider server on a local Wi-Fi network.
Since there is no APNs, you need to define your own protocol between the provider server and the app extension to deliver the notifications. Your app must specify the Wi-Fi networks where you wish to enable Local Push Connectivity for your app users. The system starts the app extension when the device joins the specified Wi-Fi networks. The app extension is responsible for maintaining a network connection with the provider server and receiving the notifications. The app extension continues to run in the background as long as the device is associated to the specified Wi-Fi networks. The system stops the app extension when the device loses connection to the specified Wi-Fi networks. Now, since we know about the new Local Push Connectivity API and also we reviewed the standard push notifications, I would like to talk about general guidelines on selecting the right API for your apps.
You should prefer either PushKit or the UserNotifications framework for your general push notifications requirements. The Local Push connectivity API is designed for a small set of very specific use cases. The use cases are mainly defined by limitations in network environments and users' requirements in those environments. Local Push Connectivity can be the right solution in scenarios where notifications are essential and network environments have constraints. To implement these specific use cases using the Local Push Connectivity API, you will need to request the new entitlement. Let's now see how these two mechanisms look in comparison with each other. New Local Push Connectivity is all about direct communication between your provider server and your app extension using your protocol on your specified Wi-Fi networks. It's completely in your control.
Now, let's understand how the app extension handles different types of notifications.
On receiving user-facing notifications, your app extension uses local notifications to get the user's attention. App Extension code uses the UserNotifications framework to create and schedule local notifications. It can display an alert, play a sound, or badge your app's icon. For example, on receiving the notification for a text message, the user can be notified using a banner rolling from the top of the screen, as shown here. The app extension should always use user Local Notifications for user facing notifications.
Now, let's see how the app extension can handle a VoIP notification. This notification conveys information about an incoming VoIP call for your app user.
On receiving a VoIP notification, the app extension uses the NEAppPushProvider class to report the incoming call to the system. In response to that, system wakes your containing app if it's not running and delivers the call info to it. The containing app uses CallKit framework to display the incoming call UI as shown here. I will talk about how to handle VoIP notifications in your app in detail later.
Now, let's see this working in a demo app. Cruise ships have limited or no internet connectivity, or sometimes they offer paid data plans. The cruise ship company in the demo has developed an app named SimplePush, which is using the new Local Push Connectivity API to provide text messaging and VoIP services. They want friends and families on board to stay in touch using this app. Jane and John are users of this app. In the demo, they communicate with each other using the SimplePush app while their devices don't have an internet connection.
This is Jane's device, and this is John's device. Let's take a look at the settings in the Simple Push app on Jane's device. The setting consists of provider server's hostname and the SSID of the Wi-Fi network where Local Push Connectivity is enabled. As you can see here, Jane's device is connected to Cruise Ship Wi-Fi. These are Jane's contacts. I will have Jane send a text message to John. That will show a notification on John's device. So let's go ahead and select John from the contacts and tap the text button. I will type in, "Hello John!" and tap the send button. And the notification appeared on John's device. John taps the notification to open the text message in the SimplePush app. Now Jane makes a voice call to John.
And that shows the incoming call UI on John's device. John answers the call, and you can see here, the call is in progress. Now, John hangs up the call.
So that was a brief demo of the SimplePush app that uses the new Local Push Connectivity API in iOS 14. The new Local Push Connectivity API comprises two classes: NEAppPushManager and NEAppPushProvider. NEAppPushManager class is used by the containing app, and app extension code implements a subclass of NEAppPushProvider class.
Your app extension and the containing app both need to have the NEAppPushProvider entitlement to use this API. The containing app uses an instance of the NEAppPushManager class to create a configuration, which mainly consists of Wi-Fi networks where Local Push Connectivity is expected to work. You can load, save, and remove a configuration using this class. If you're implementing a VoIP app, the NEAppPushManager class is also used to set a delegate to handle the incoming VoIP calls. Your app extension implements a subclass of the NEAppPushProvider class. This class defines life cycle management methods that you need to override in your subclass.
The methods are called by the system when the app extension is started and stopped. The app extension is started when the device joins the specified Wi-Fi networks. The system stops the app extension when the device loses the connection with the specified Wi-Fi networks. The app extension establishes a network connection with its provider server on start, and tears down the connection on stop. On receiving a VoIP notification, the app extension uses this class to report the incoming call to the system. In response to that, the system wakes the containing app and delivers the call info to it.
Now let's take a look at how your app uses the NEAppPushManager class to create a configuration. You need to import the NetworkExtension module to use the Local Push Connectivity API. Creating a configuration for your app push provider is very simple. You need to create an instance of the NEAppPushManager class, and use that to set these properties. "matchSSIDs" specifies an array of SSIDs of the Wi-Fi networks where you wish to enable Local Push Connectivity. "providerBundleIdentifier" is the bundle identifier of your app extension. This setting allows the system to run the appropriate app extension, when needed. "providerConfiguration" is a dictionary that specifies configuration data for your app extension. And finally, you need to set isEnabled to true in order to enable Local Push Connectivity using this configuration. After you have all the settings configured, call saveToPreferences method to persist the configuration. If the configuration is saved successfully and it is enabled, the system enables Local Push Connectivity using this configuration. The app extension implements a subclass of the NEAppPushProvider class and overrides the required methods. The system calls startWithCompletionHandler to start the app extension. The app extension establishes a network connection with its server in this method. The system calls stopWithReason when the app extension is stopped. The app extension tears down the server connection in this method.
Upon receiving a VoIP notification, the app extension calls reportIncomingCall to report the incoming VoIP call to the system. In response to that, the system wakes the containing app, if it's not running, and delivers the call info to it. As we saw in the last slide, the app extension is responsible for reporting incoming VoIP call to the system, and in response, the system launches the app.
The containing up must implement an app delegate object conforming to UIApplicationDelegate protocol in order to know when app process is launched.
On app launch, you must call loadAllFromPreferences to load all the saved configurations, and set the NEAppPushDelegate object for each NEAppPushManager instance as shown here. The system delivers the user info dictionary to the containing app by calling the didReceiveIncomingCallWithUserInfo delegate method for the appropriate NEAppPushManager instance on the app's main queue. On receiving the user info, the app must report the incoming call to CallKit using the appropriate CallKit API and let it display the call UI.
Please see the CallKit API documentation for the details on reporting incoming calls, and also refer to the SimplePush sample app code for more details.
Please note, in order to receive incoming call info, your containing app must have the "Voice over IP" background mode enabled in the Xcode Project > Capabilities pane as shown here. Now, you know the details of the new Local Push Connectivity API introduced in iOS 14. Let's talk about the next steps you should take to use notifications in your app. You should prefer either PushKit or the UserNotifications framework for most general push notifications requirements in your app.
You should use Local Push Connectivity only in network conditions where APNs connectivity is not available, and notifications are essential for your app users.
If you determine Local Push Connectivity is the right solution for your app users, remember that you must request the NEAppPushProvider entitlement
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.