📘

[iOS]コマンドラインからPush通知を送る

2022/03/01に公開

iOSのPush通知はFirebase FCMで送ると簡単なのですが、細かい機能までできているか気になったのでApple公式の方法で調べました。
公式の方法を知っておくと、FCMでも同じような送信オプションなどを探しやすくなると考えています。

以下の公式ページを参考にしています。
Sending Push Notifications Using Command-Line Tools | Apple Developer Documentation

アプリの準備

事前に、アプリの登録を行う必要があります。
Registering Your App with APNs | Apple Developer Documentation

プロジェクトを作成したら、プロジェクト設定 > Targets > Signing Capabilitiesより「+ Capability」ボタンを押して「Push Notification」を追加します。自動でApp Bundle IDが登録されます。com.example.MyAppのような形式です。

証明書の登録〜書き出し

Cerファイル

最初に、証明書署名リクエスト(.certSigningRequest)を作成します。
証明書署名リクエストを作成する - デベロッパアカウントヘルプ

次に、Cerファイル(証明書)を発行します。
Establishing a Certificate-Based Connection to APNs | Apple Developer Documentation

以下のページにアクセスします。
Certificates, Identifiers & Profiles

  • Apple Push Notification services SSL (Sandbox & Production)を選択します。
  • App Bundle IDを選択します。
  • 証明書署名リクエスト(.certSigningRequest)をアップロードします
  • 生成されたファイルをダウンロードします
  • ファイルをクリックし、Keychain Accessに追加します

Pemファイル

  • Keychain Access > システムルート > 証明書を選択します
  • 先ほど追加した証明書を開きます
  • 「>」マークをクリックし、秘密鍵も表示します
  • 証明書・秘密鍵を選択し、右クリックで書き出しを選択します。形式はp12です

p12からpemに変換します。

% openssl pkcs12 -in pushcert.p12 -out pushcert.pem -nodes -clcerts

これでpemファイルが生成されます。

追加の証明書を確認

もし、前述のKeychain Accessで該当の証明書を確認した際、「この証明書は信頼されていません」のエラーが出た場合、追加の証明書をKeychain Accessにインストールする必要があります。

Certificates, Identifiers & Profiles
ここのページの一番下に、4つほど証明書がありますので、ダウンロードしてインストールします。

Worldwide Developer Relations Certificate Authority (Expiring 02/07/2023)
Worldwide Developer Relations Certificate Authority (Expiring 02/20/2030)
Worldwide Developer Relations - G4 (Expiring 12/10/2030)
Developer ID - G2 (Expiring 09/17/2031)

APNsに接続確認

APNsへ接続をテストしてみます。

#!/bin/bash

CERTIFICATE_FILE_NAME=pushcert.cer
CERTIFICATE_KEY_FILE_NAME=pushcert.pem
TOPIC=com.example.MyApp
DEVICE_TOKEN=<Your device token>
APNS_HOST_NAME=api.sandbox.push.apple.com

# 接続をテスト
openssl s_client -connect "${APNS_HOST_NAME}":443 -cert "${CERTIFICATE_FILE_NAME}" -certform DER -key "${CERTIFICATE_KEY_FILE_NAME}" -keyform PEM

Device Tokenの文字列の取得方法

func application(_ application: UIApplication,
            didRegisterForRemoteNotificationsWithDeviceToken 
                deviceToken: Data) {
	let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
}

APNsに送信

#!/bin/bash

CERTIFICATE_FILE_NAME=pushcert.cer
CERTIFICATE_KEY_FILE_NAME=pushcert.pem
TOPIC=com.example.MyApp
DEVICE_TOKEN=<Your device token>
APNS_HOST_NAME=api.sandbox.push.apple.com

curl -v --header "apns-topic: ${TOPIC}" --header "apns-push-type: alert" --cert "${CERTIFICATE_FILE_NAME}" --cert-type DER --key "${CERTIFICATE_KEY_FILE_NAME}" --key-type PEM --data '{"aps":{"alert":"test"}}' --http2  https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

オプションを試す

APNsのオプションにはいくつもの機能があります。

ヘッダーのオプション

Sending Notification Requests to APNs | Apple Developer Documentation

ヘッダーの中で、重要なオプションを列挙します。

  • apns-push-type
    • プッシュ通知のタイプ。watchOSでは必須で、それ以外のプラットフォームでは推奨となっています。設定しておいた方が良いでしょう。
    • alert, background, locationなどがあります
  • apns-priority : 配信の優先度
  • apns-topic : App Bundle ID
  • apns-collapse-id
    • 通知のID
    • 同じIDにすることで、以前の通知を上書きできます

Payloadのオプション

JSON Payloadのオプションは以下のページで確認できます。

Generating a Remote Notification | Apple Developer Documentation

  • loc-keyなどでローカライズもできます
  • soundでカスタムの通知音を設定できます
  • categoryでアクションを選択できます

他にも細かいオプションがあります。

Discussion