Goalist Developers Blog

iOS10でプッシュ通知を実装してみた

こんちは。渡部です。

今回はプッシュ通知についてです。
プッシュ通知はリモートだと証明書やらで非常に面倒になります。
なので比較的に簡単な実装方法を紹介します。

f:id:watabe1028:20170831132743j:plain

プッシュ通知とは?

プッシュ通知とは、システム側が外部のサーバーと連携して能動的に情報を取得してユーザーに通知する方式のことである。

www.weblio.jp

要は外部から通知が届く仕組みです。

LINEとかメッセージ届くときますよね?
あれです。

動作環境

・macOS Sierra(10.12.6)

・Xcode8.3.2(古い!)

・Swift3.0(古い!)

・実機(iPhone SE iOS10.2 古い!)

注意点

・シミュレータでは検証できないので実機でおねしゃす!

・AppleDeveloperProgramには加入済み前提で進めます。
・証明書CSRファイルは取得済み前提です。

・今回はAdHocでやります。

・訳あってiOS、Xcodeとも古いままです。

・サーバサイドはノータッチ!

プッシュ通知の種類

リモートとローカル

簡単に言うと、ローカルはアプリ側のプログラムで通知が完結するもの

リモートは外部のサーバを使って通知を可能にするもの

と自分は定義しています。

プッシュ?リッチ?ペイロード?なんぞ?


通常のプッシュ通知のみの実装がプッシュ通知、
プッシュ通知を開くとWebViewが表示できるのがリッチプッシュ、
プッシュ通知からメッセージなどのデータをペイロード取得
する通知があります。

今回は面倒なのでシンプルなリモートのプッシュ通知です。
次回はローカルの記事を書くかもしれません。
書かないかもしれません。
詳しい仕組みは偉人たちの記事を参照してください(投げやり) 。

チャット風メッセージアプリを作ります。
Web側のメッセージ送信時にアプリがフォアグラウンドにない場合に
通知を表示させるだけの簡単な仕様です。
チャット? どうやって作んの?の人はこちら

今回は画像付きで長くなるで!

手順


・APNs証明書作成
・アプリの設定

・コーディング

・実行

APNs証明書作成

AppleDeveloperにログインし、「Certificates,IDs & Profiles」を選択します。
右ペインのメニューから「Certificates」を選択し、右上の「+」ボタンで証明書を作成します。

Apple Push Notification service SSL(Sandbox)を選択し

f:id:watabe1028:20170831152540p:plain

使いたいアプリのApp IDを選択します。

f:id:watabe1028:20170831152601p:plain

このページは華麗にスルー

f:id:watabe1028:20170831152616p:plain

CSRファイルを選択すればおけ!

f:id:watabe1028:20170831152632p:plain

アプリの設定

まずプロジェクトでプッシュ通知を使うための設定をします。
プロジェクトを選択し、「Capabilities」から「Push Notifications」と「Background Modes」をONにします。
f:id:watabe1028:20170831132308p:plain

「Background Modes」は「Background fetch」と「Remote Notifications」にチェックを入れます。 f:id:watabe1028:20170831132324p:plain

コーディング


プッシュ通知の基本ですが通知を受け取るには許可が必要です。

許可をもらった後に、デバイストークンを取得してサーバサイドに渡す必要があります。
いくつか注意点があるのでコメントを読んでください。

まずはインポートとDelegateの設定です。

import UIKit
import UserNotifications  // インポートする

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, networkManagerDelegate, UNUserNotificationCenterDelegate { // Delegateの追加を忘れずに

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

didFinishLaunchingWithOptionsで通知の設定をします。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
                
        if #available(iOS 10.0, *) {
            
            //ios10
            let center = UNUserNotificationCenter.current()
            center.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { (granted, error) in
                if error != nil {
                    return
                }
                if granted {
                    debugPrint("通知許可")
                    center.delegate = self
                    application.registerForRemoteNotifications()
                } else {
                    debugPrint("通知拒否")
                }
            })
            
        } else {
            // ios9
            let settings = UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)
            UIApplication.shared.registerUserNotificationSettings(settings)
            UIApplication.shared.registerForRemoteNotifications()
        }
        
        return true
    }

通知が許可された場合の処理です。
ここでデバイストークンを取得します。
以降もずっとこのデバイストークンを使うのでUserDefaults等に保存しておきます。

    //リモート通知
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        // そのままだと「32bit」という文字列なので以下の処理を行います
        let deviceTokenString: String = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
        print("deviceTokenString \(deviceTokenString)")
        util.setUserDefaultsObject(value: deviceTokenString, key: udDeviceToken) // これは自前
    }

逆に通知が許可されなかった場合の処理です。

    //リモート通知を拒否したときの動作
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
        debugPrint("リモート通知の設定は拒否されました")
    }

ここまで書けば一応動きます。
通知が来た時、通知から起動した時は
withCompletionHandlerなどを使います。
もちろん、はしょります。

実行


ビルドして実機にインストールします。
ここでビルド成功後にエラーが出たりしますがそこは頑張ってください。

多分プロビジョニングとかが悪さしてることが多いです。
今回は速攻で通知の許可アラートが表示されるはずです。
f:id:watabe1028:20170831131756p:plain

許可した後にアプリを一度バックグラウンドにします。
Web側でメッセージを送信! f:id:watabe1028:20170831131816p:plain

来た!
f:id:watabe1028:20170831131829p:plain

おまけ


サーバサイドはノータッチとしてましたが
今回はAWSのこちらを使っています。
aws.amazon.com

まとめ

準備から実装まで面倒なプッシュ通知ですが
ユーザーのアプリ復帰率を上げるためには必須と言えます。
通知自体もだんだんリッチになるので
今のうちに簡単な通知ができるようになった方が良いな、と思いこの記事を書きました。
どこかの誰かのお役に立てればと思います。