1. 程式人生 > >Send Push Notifications to iOS Devices using Xcode 8 and Swift 3, APNs Auth Key

Send Push Notifications to iOS Devices using Xcode 8 and Swift 3, APNs Auth Key

Send Push Notifications to iOS Devices using Xcode 8 and Swift 3

OCT 6, 2016

Push notifications are a great way to ensure your users re-engage with your app every once in a while, but implementing them on iOS can be challenging, especially with all of the changes in Xcode and Swift, not to mention the various iOS versions which deprecate the notification classes we grew accustomed to in the past.

The Internet is overflowing with guides on how to implement iOS push notifications -- however, many of these guides are cumbersome, complicated, not up-to-date with Swift 3 and Xcode 8, and/or don't provide backward-compatibility with all iOS versions that support Swift (iOS 7 - iOS 10). Also, they do not make use of the new APNs Auth Keys which greatly simplify the steps involved in sending push notifications.

By following this guide, you'll be able to implement push notifications in your iOS app and send notifications from Node.js, using the latest technologies and without much hassle!

Demo

Preparations

First off, open your iOS project in Xcode 8. If you don't have Xcode 8 yet, be sure to update via the App Store. If you don't have an iOS project yet, simply create a new one. Make sure that your codebase has been updated to use Swift 3.

Second, make sure that you have an active Apple Developer Program Membership, which costs $100/year. It is a requirement in order to send push notifications to your iOS app. Also, make sure Xcode is configured to use the iCloud account which contains your active Apple Developer Program Membership.

Third, make sure that your app has a Bundle Identifier configured in the project editor:

Bundle Identifier

Enabling Push Notifications

The first step in setting up push notifications is enabling the feature within Xcode 8 for your app. Simply go to the project editor for your target and then click on theCapabilities tab. Look for Push Notifications and toggle its value to ON:

Toggle Capability

Xcode should display two checkmarks indicating that the capability was successfully enabled. Behind the scenes, Xcode creates an App ID in the Developer Center and enables the Push Notifications service for your app.

Registering Devices

Devices need to be uniquely identified to receive push notifications.

Every device that installs your app is assigned a unique device token by APNs that you can use to push it at any given time. Once the device has been assigned a unique token, it should be persisted in your backend database.

A sample device token looks like this:

5311839E985FA01B56E7AD74334C0137F7D6AF71A22745D0FB50DED665E0E882  

To request a device token for the current device, open AppDelegate.swift and add the following to the didFinishLaunchingWithOptions callback function, before the return statement:

// iOS 10 support
if #available(iOS 10, *) {  
    UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
    application.registerForRemoteNotifications()
}
// iOS 9 support
else if #available(iOS 9, *) {  
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
    UIApplication.shared.registerForRemoteNotifications()
}
// iOS 8 support
else if #available(iOS 8, *) {  
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
    UIApplication.shared.registerForRemoteNotifications()
}
// iOS 7 support
else {  
    application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}

In iOS 10, a new framework called UserNotifications was introduced and must be imported in order to access the UNUserNotificationCenter class.

Add the following import statement to the top of AppDelegate.swift:

import UserNotifications  

Next, go to the project editor for your target, and in the General tab, look for the Linked Frameworks and Libraries section.

Click + and select UserNotifications.framework:

UserNotifications.framework

Next, add the following callbacks in AppDelegate.swift which will be invoked when APNs has either successfully registered or failed registering the device to receive notifications:

// Called when APNs has assigned the device a unique token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {  
    // Convert token to string
    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})

    // Print it to console
    print("APNs device token: \(deviceTokenString)")

    // Persist it in your backend in case it's new
}

// Called when APNs failed to register the device for push notifications
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {  
    // Print the error to console (you should alert the user that registration failed)
    print("APNs registration failed: \(error)")
}

It's up to you to implement logic that will persist the token in your application backend. Later in this guide, your backend server will connect to APNs and send push notifications by providing this very same device token to indicate which device(s) should receive the notification.

Note that the device token may change in the future due to various reasons, so useNSUserDefaults, a local key-value store, to persist the token locally and only update your backend when the token has changed, to avoid unnecessary requests.

Run your app on a physical iOS device (the iOS simulator cannot receive notifications) after making the necessary modifications to AppDelegate.swift. Look for the following dialog, and press OK to permit your app to receive push notifications:

Alert Dialog

Within a second or two, the Xcode console should display your device's unique token. Copy it and save it for later.

Prepare to Receive Notifications

Add the following callback in AppDelegate.swift which will be invoked when your app receives a push notification sent by your backend server:

// Push notification received
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {  
    // Print notification payload data
    print("Push notification received: \(data)")
}

Note that this callback will only be invoked whenever the user has either clicked or swiped to interact with your push notification from the lock screen / Notification Center, or if your app was open when the push notification was received by the device.

It's up to you to develop the actual logic that gets executed when a notification is interacted with. For example, if you have a messenger app, a "new message" push notification should open the relevant chat page and cause the list of messages to be updated from the server. Make use of the data object which will contain any data that you send from your application backend, such as the chat ID, in the messenger app example.

It's important to note that in the event your app is open when a push notification is received, the user will not see the notification at all, and it is up to you to notify the user in some way. This StackOverflow question lists some possible workarounds, such as displaying an in-app banner similar to the stock iOS notification banner.

Generate an APNs Auth Key

The next step involves generating an authentication key that will allow your backend server to authenticate with APNs when it wants to send one or more of your devices a push notification.

Up until a few months ago, the alternative to this was a painful process that involved filling out a Certificate Signing Request in Keychain Access, uploading it to the Developer Center, downloading a signed certificate, and exporting its private key from Keychain Access (not to mention converting both certificates to .pem format). This certificate would then expire and need to be renewed every year and would only be valid for one deployment scheme: Development or Production.

Thankfully, Apple has greatly simplified the process of authenticating with APNs with the introduction of APNs Auth Keys, which never expire (unless revoked by you) and work for all deployment schemes.

Open the APNs Auth Key page in your Developer Center and click the + button to create a new APNs Auth Key.

APNs Auth Key

In the next page, select Apple Push Notification Authentication Key (Sandbox & Production) and click Continue at the bottom of the page.

APNs Selection

Apple will then generate a .p8 key file containing your APNs Auth Key.

Download Key

Download the .p8 key file to your computer and save it for later. Also, be sure to write down the Key ID somewhere, as you'll need it later when connecting to APNs.

Send Push Notifications

Now it's time to set up your backend to connect to APNs to send notifications to devices! For the purpose of this guide and for simplicity, I'll choose to do this in Node.js. If you already have a backend implemented in another development language, look for another guide better-tailored for you, or simply follow along to send a test push notification to your device.

Make sure you have Node.js v4 or newer installed on your local machine and run the following in a directory of your choice:

mkdir apns  
cd apns  
npm init --yes  
npm install apn --save  

These commands will initiate a new Node.js project and install the amazing apn package from npm, which authenticates with APNs and sends your push notifications.

Next, copy the .p8 file you just downloaded into the apns folder we created. Name it apns.p8 for simplicity.

Create a new file in the apns folder named app.js using your favorite editor, and paste the following code inside:

var apn = require('apn');

// Set up apn with the APNs Auth Key
var apnProvider = new apn.Provider({  
     token: {
        key: 'apns.p8', // Path to the key p8 file
        keyId: 'ABCDE12345', // The Key ID of the p8 file (available at https://developer.apple.com/account/ios/certificate/key)
        teamId: 'ABCDE12345', // The Team ID of your Apple Developer Account (available at https://developer.apple.com/account/#/membership/)
    },
    production: false // Set to true if sending a notification to a production iOS app
});

// Enter the device token from the Xcode console
var deviceToken = '5311839E985FA01B56E7AD74444C0157F7F71A2745D0FB50DED665E0E882';

// Prepare a new notification
var notification = new apn.Notification();

// Specify your iOS app's Bundle ID (accessible within the project editor)
notification.topic = 'my.bundle.id';

// Set expiration to 1 hour from now (in case device is offline)
notification.expiry = Math.floor(Date.now() / 1000) + 3600;

// Set app badge indicator
notification.badge = 3;

// Play ping.aiff sound when the notification is received
notification.sound = 'ping.aiff';

// Display the following message (the actual notification text, supports emoji)
notification.alert = 'Hello World \u270C';

// Send any extra payload data with the notification which will be accessible to your app in didReceiveRemoteNotification
notification.payload = {id: 123};

// Actually send the notification
apnProvider.send(notification, deviceToken).then(function(result) {  
    // Check the result for any failed devices
    console.log(result);
});

There are several things to do before running this code:

  1. Configure the teamId property with your Apple Developer Account Team ID (available at https://developer.apple.com/account/#/membership/)
  2. Configure deviceToken with the device token you generated after running your application and checking the console
  3. Configure notification.topic with your application's Bundle ID which is accessible in the project editor

Now, lock your device, run node app.js and lo-and-behold, provided you did everything right, your iOS device should be able to receive the notification!

Done

Interacting with the notification will print the following in your Xcode console since didReceiveRemoteNotification is invoked:

[AnyHashable("id"): 123, AnyHashable("aps"): {
    alert = "Hello World \U270c";
    badge = 3;
    sound = "ping.aiff";
}]

I hope you were able to get through this tutorial with ease. Let me know if this helped you in the comments below!

相關推薦

Send Push Notifications to iOS Devices using Xcode 8 and Swift 3, APNs Auth Key

Send Push Notifications to iOS Devices using Xcode 8 and Swift 3 OCT 6, 2016 Push notifications are a great way to ensure your users re-engage with your

Implement Push Notifications in iOS with Swift

Implement Push Notifications in iOS with Swift https://medium.com/@franciscoigor/implement-push-notifications-in-ios-with-swift-ca6d962ae214

[PWA] Add Push Notifications to a PWA with React in Chrome and on Android

On Android and in Chrome (but not on iOS), it's possible to send push notifications with a PWA. We'll start by asking the user for permission to send them

These are the best free courses to help you learn Java 8 and Java 9

These are the best free courses to help you learn Java 8 and Java 9“ceramic coffee mug filled with coffee” by Athena Lam on UnsplashAfter the introduction

How to read version (and other) information from Android and iOS apps using Java

How to read version (and other) information from Android and iOS apps using Java https://medium.com/@mart.schneider/how-to-read-version-and-oth

add the push notifications entitlement to your entitlements file

add the push notifications entitlement to your entitlements file p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 19.0px; font: 13.0px "Helvetica Neue

[iOS] How to segue programmatically using swift

If your segue exists in the storyboard with a segue identifier between your two views, you can just call it programmatically using: performSegue(withIdent

友盟統計出現Add the Push Notifications feature to your App ID.的錯誤

最近在整合友盟推送的時候,出現了一個錯誤, 1:後來把自動管理證書的勾給勾上,就好了 2:手動管理證書的時候,如果兩個環境的描述檔案都沒有錯誤,但是打開了push notifications的開關就steps1錯誤的話,及可以重啟Xcode就好了

Extend AWS DeepLens to Send SMS Notifications with AWS Lambda

AWS DeepLens is a deep learning enabled developer toolkit with a video camera. It enables you to develop machine learning skills using hands-on co

Xcode 8以上 Update to recommended setting 提示警告

xcod data- digg class trac spi ref -m hang 這是建議你更新設置,建議是開啟Suspicious Moves這個編譯警告。這是一個Xcode中新增的編譯警告。 點擊Prefrom Changes就可以啦! Xcode

安裝xcode6 beta 後調試出現Unable to boot the iOS Simulator以及編譯蘋果官方Swift的demo報錯failed with exit code 1的解決的方法

imu fonts mat 詳細說明 watermark data- 重新啟動 技術分享 說明 蘋果昨天公布新語言Swift(雨燕),須要安裝xcode6 以及mac os 系統為10.9以上。 (xcode6 beta 可在官方下載。須要登錄開發人員賬號;mac os

【轉1】Appium 1.6.3Xcode 8, iOS 10.2(模擬器)測試環境搭建 經驗總結

div tar post bug span trace 版本 test 4.0 Appium 1.6.3 在Xcode 8, iOS 10.2(模擬器)測試環境搭建 經驗總結 關於 Appium 1.6.3 在Xcode 8, 10.2 的iOS模擬器上的問

iOS 11系列 - Xcode 9新特性

rsa cti 連接數 項目 threads 比較 title and val Xcode 9最近剛剛發布,帶來了一系列不錯的新特性,可以更好的幫助到開發者完成開發工作。 Xcode Runtime Tool Xcode 9中有許多Runtime Tool可以幫助開發者找到

IOS+openCV在Xcode的入門開發(轉)

運行環境 pix xcod fss return 小白 some 文件夾 步驟 看這篇文章之前先看看這個地址:OpenCV iOS開發(一)——安裝 昨天折騰了一天,終於搞定了openCV+IOS在Xcode下的環境並且實現一個基於霍夫算

Note 1 for <Pratical Programming : An Introduction to Computer Science Using Python 3>

3.3 整數 dir 運算 aso mbo int edt log Book Imformation : <Pratical Programming : An Introduction to Computer Science Using Python 3> 2n

python多版本配置後使用pip出現 Fatal error in launcher: Unable to create process using '"'

com num cnblogs src eat sta reat xxxxx 。。 上一篇剛介紹了python的多版本環境配置,然後再我把python2的python.exe改成python2.exe之後,python2的pip就不好使了,出現了如題的錯誤。。。 然後解決辦

Note 2 for <Pratical Programming : An Introduction to Computer Science Using Python 3>

follow more bject eval 3.1 語法 val sin pau Book Imformation : <Pratical Programming : An Introduction to Computer Science Using Python

[轉發]解決 git push Failed to connect to 127.0.0.1 port 45463: 拒絕連接

pre host 導致 占用 span www. git push github con 使用Github pull 代碼突然報錯: Failed to connect to 127.0.0.1 port 43421: Connection refused 使用 ls

pip安裝出現Fatal error in launcher: Unable to create process using '"'的解決辦法

python2 情況 是否 bubuko inf img where class 控制 python中使用pip安裝模塊時,出現:Fatal error in launcher: Unable to create process using ‘"‘ 原因:系統中可能有多處安

python2.7升級到python3後,用pip進行安裝時報Fatal error in launcher:Unbale to create process using`""

com AR net tar 完成 ng- htm o-c www 解決:python2.7升級到python3後,用pip進行安裝時報Fatal error in launcher:Unbale to create process using`"" 通過查資料查到:htt