iOS アプリへプッシュ通知を実装する

iOS アプリへプッシュ通知を実装し、プッシュトークンを得るための実装方法をご紹介します。

iOS ではプッシュ通知にあたって、ユーザーの許可を得る必要があることに留意が必要です。

対象とするバージョンの検討

iOS でのプッシュ通知の実装方法はバージョンを経ることに変わっています。このため、古いバージョンをサポートするアプリの場合、新しいバージョンの OS と古いバージョンの OS で処理を分け、それぞれのバージョンに合わせた方法で実装します。古いバージョンの実装が最近のOSで動いても、その後のバージョンの OS で無効とされる可能性があるため、できるだけ新しい方法で実装しておく必要があります。

新しいバージョンの時の動作と古いバージョンの時の動作を分けるには、以下のような方法を使います。

1
2
3
4
5
6
7
// Swift の場合
if #available(iOS 10.0) {
    // iOS 10 以降
}
else {
    // それ以下
}
1
2
3
4
5
6
7
// Objective-C の場合
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_10_0) {
    // iOS 10 未満
}
else {
    // iOS 10 以上
}

iOS 10 以降の実装方法

iOS 10 以降では通知の表示に UserNotification フレームワークを使用します。

通知の許可を要求する

インストール後、初回の UNUserNotificationCenter.current().requestAuthorization(options:, completionHandler:) メソッドの呼び出し時に、ユーザーに通知許可要求ダイアログが表示されます。許可されたら UIApplication.shared.registerForRemoteNotifications() でプッシュトークンを取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// options で使いたい通知の種類 (alert: メッセージ, .badge: バッジ表示, .sound: 音) を指定する
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
    if (granted) {
        // options で要求した通知がすべて許可された

        // プッシュトークンを要求する
        UIApplication.shared.registerForRemoteNotifications()
    }
    else {
        // 通知のいずれかが許可されなかった
    }
}

プッシュトークンを取得する

UIApplication.shared.registerForRemoteNotifications() の呼び出し後、AppDelegate の application(_:didRegisterForRemoteNotificationsWithDeviceToken:) デリゲートメソッドが呼び出されます。

この中で、サーバーへ送信する処理を記述します。トークンは Data(NSData) クラスのインスタンスで渡されるので、適宜エンコードが必要となります。

1
2
3
4
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let tokenString = deviceToken.hexadecimalString
    // tokenString をサーバーへ送信する処理を記述する
}

BoltzEngineで使用するHexエンコーディングへの変換はBoltzMessengerSDK内に含まれるDataExtension.swiftに定義されており、これを取り込むことでhexadecimalStringが追加されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
extension Data {
    public var hexadecimalString: NSString {
        var bytes = [UInt8](repeating: 0, count: count)
        copyBytes(to: &bytes, count: count)
        
        let hexString = NSMutableString()
        for byte in bytes {
            hexString.appendFormat("%02x", UInt(byte))
        }
        
        return NSString(string: hexString)
    }
}

通知の許可状態を検出する

ユーザーが通知を許可しているかどうかは UNUserNotificationCenter.current().getNotificationSettings(completionHandler:) で検出できます。

トークン送信中にアプリを終了されるなどのエラーに備えて、アプリ起動後1回実行し、許可されていればregisterForRemoteNotifications() を実行するといった処理を記述することをお勧めします。

1
2
3
4
5
6
UNUserNotificationCenter.current().getNotificationSettings { (setting) in
    if setting.authorizationStatus == .authorized {
        // 許可されている
        UIApplication.shared.registerForRemoteNotifications()
    }
}

iOS 8〜9での実装方法

iOS 8〜9の場合は、UIUserNotificationSettings を作成して UIApplication に登録します。

通知の許可を要求する

インストール後、初回の UIApplication.shared.registerUserNotificationSettings(types:categories:) メソッドの呼び出し時に、ユーザーに通知許可要求ダイアログが表示されます。

1
2
let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)

許可または不許可が判明すると、 AppDelegate の application(_:, didRegister:) デリゲートメソッドが呼ばれます。この中で引数の UIUserNotificationSettings を使って通知が許可されたかどうかを判定します。通知の利用が許可されていれば UIApplication.shared.registerForRemoteNotifications() でプッシュトークンを取得します。

1
2
3
4
5
6
7
8
9
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
    if notificationSettings.types != .none {
        // 何らかの通知が許可されている
        UIApplication.shared.registerForRemoteNotifications()
    }
    else {
        // 通知が全て不許可の状態
    }
}

プッシュトークンを取得する

iOS 10 以降の時と同様、AppDelegate の application(_:didRegisterForRemoteNotificationsWithDeviceToken:) デリゲートメソッドが呼び出されますので、この中にサーバーへ送信する処理を記述します。

通知の許可状態を検出する

ユーザーが通知を許可しているかどうかは UIApplication.shared.currentUserNotificationSettings で検出できます。ここには通知の許可を取得した時と同じ UIUserNotificationSettings が得られます。

トークン送信中にアプリを終了されるなどのエラーに備えて、アプリ起動後1回実行し、許可されていれば registerForRemoteNotifications() を実行するといった処理を記述することをお勧めします。

1
2
3
4
5
6
if let settings = UIApplication.shared.currentUserNotificationSettings {
    if settings.types != .none {
        // 何らかの通知が許可されている
        UIApplication.shared.registerForRemoteNotifications()
    }
}

iOS 7未満での実装方法

通知の許可を要求する

インストール後、初回の UIApplication.shared.registerForRemoteNotifications(matching:) メソッドの呼び出し時に、ユーザーに通知許可要求ダイアログが表示されます。

1
UIApplication.shared.registerForRemoteNotifications(matching: [.alert, .badge, .sound])

プッシュトークンを取得する

iOS 10以降の時と同様、AppDelegateの application(_:didRegisterForRemoteNotificationsWithDeviceToken:) デリゲートメソッドが呼び出されますので、この中にサーバーへ送信する処理を記述します。

通知の許可状態を検出する

UIApplication.shared.enabledRemoteNotificationTypes() から、現在許可されている通知の種別を取得できます。

トークン送信中にアプリを終了されるなどのエラーに備えて、アプリ起動後1回実行し、許可されていれば registerForRemoteNotifications(matching:) を実行するといった処理を記述することをお勧めします。

1
2
3
4
5
let types = UIApplication.shared.enabledRemoteNotificationTypes()
if types != .none {
    // 何らかの通知が許可されている
    UIApplication.shared.registerForRemoteNotifications(matching: [.alert, .badge, .sound])
}

通知の許可ダイアログを表示するタイミングの検討

通知許可要求ダイアログは、急に表示されるとそのアプリがどのような通知を表示するかがわからず、「拒否」を選択する可能性があります。

むやみに通知許可要求ダイアログを出さずに、「通知の許可状態を検出する」の方法で通知が許可されているかどうかを判定し、初回の要求と判断できる場合については「このアプリがどのような通知を出すのか」といった説明画面を表示させるという方法をとることをお勧めします。

また、メッセージングアプリなど、通知がないとUXが大きく下がるアプリに関しては同様に通知不許可の状況に対して通知の許可を与えるようユーザーに促すことも可能です。このとき、以下のような記述で設定アプリへ遷移させることも可能です。

1
2
let url = NSURL(string:UIApplicationOpenSettingsURLString)
UIApplication.sharedApplication().openURL(url)

iOS8未満でプッシュトークンを更新する

iOS 8 未満の端末では通知許可要求ダイアログの選択状況はアプリを再インストールしても一定期間経たなければ変化しません。

テスト等の目的で通知許可をリセットするには、以下のような手順を実行します。(Apple Technical Note TN2265)

  1. アプリをアンインストールします。
  2. 端末を再起動します。
  3. 設定→一般→日付と時刻 を開き、日付を進めます。
  4. 再度端末を再起動します。

ご不明な点はありませんか?

機能の詳細、導入のご検討、お見積もり依頼などは、お気軽にお問い合わせください。
担当者から追ってご連絡いたします。

お問い合わせはこちら