Device Tokenは、APNSがプッシュ通知をルーティングするために各iOSデバイスに割り当てる一意の識別子です。トークンはアプリが通知を受信するために登録する際にシステムによって生成され、このデバイスにプッシュを送信するためにサーバーに送信される必要があります。Apple Developer Documentation、2026年によると、Device Tokenはアプリの再インストール、バックアップからのデバイス復元、またはiOSのアップデート時に変更される可能性があるため、サーバーは配信を確実にするために定期的にトークンを更新する必要があります。
重要ポイント
Device Token(デバイストークン)は、APNS(Apple Push Notification Service)がiOSデバイス上の各アプリに対して生成する、16進文字列形式の一意の識別子です。トークンはサーバーが特定のデバイスにプッシュ通知を送信するための鍵です。有効なDevice Tokenがないと、サーバーはプッシュ通知を配信できません。APNSは400 BadRequestエラーでリクエストを拒否します。
Device Tokenは、インストール後にアプリが初めてAPNSに接続する際にiOSシステムによって作成されます。生成プロセスには、アプリのバンドルIDとデバイスの一意の識別子(UID)への暗号学的なバインドが含まれ、その後APNSはアプリに16進形式(64文字)の32バイトトークンを返します。トークンは永続的ではありません。システムは特定の条件下で新しいトークンを生成する場合があります。
サーバーがプッシュ通知を送信する際、APNSへのHTTP/2リクエストにDevice Tokenを含めます。APNSはトークンを検証します。トークンが別の環境(本番環境ではなくサンドボックス)のものである場合、期限切れの場合、または失効している場合、Appleサーバーは410 Goneまたは400 BadRequestエラーを返します。トークンの検証が成功した後にのみ、APNSはデバイスへの通知の配信を開始します。
Device Tokenは、IDFA(広告主識別子)、IDFV(ベンダー識別子)、またはUID(一意のデバイス識別子)と混同しないでください。IDFAとIDFVは広告や分析に使用され、UIDはハードウェアのシリアル番号です。Device Tokenはプッシュ通知専用に存在し、APNSの外部でユーザーやデバイスに関する情報を開示しません。
| 識別子 | 目的 | 永続性 |
|---|---|---|
| Device Token | APNSプッシュ通知のルーティング | 変更される可能性あり |
| IDFA | 広告とトラッキング | ユーザーがリセット可能 |
| IDFV | ベンダー識別(分析) | 同じ開発者のアプリで永続的 |
| Bundle ID | アプリの一意の識別子 | 永続的 |
Device Tokenを取得するプロセスは、ユーザーに許可を求めることからサーバーにトークンを送信することまで、いくつかの必須ステップで構成されています。各ステップは重要です。いずれかをスキップすると、デバイスへのプッシュ通知の送信が不可能になります。
最初のステップは、アプリがUNUserNotificationCenter.current().requestAuthorizationを介してユーザーに通知の許可を求めることです。ユーザーは同意する、拒否する、またはオプションのオプション(アラート、バッジ、サウンド)を選択できます。明示的なユーザーの同意がないと、アプリがregisterForRemoteNotificationsを呼び出しても、システムはDevice Tokenを発行しません。許可を取得した後、アプリはUIApplication.shared.registerForRemoteNotifications()を呼び出し、APNSへの登録プロセスを開始します。
登録後、APNSはAppDelegateを介してトークンを返します:application(_:didRegisterForRemoteNotificationsWithDeviceToken:)。成功した呼び出しにはトークンを含むDataオブジェクトが含まれており、サーバーに送信するために16進文字列に変換する必要があります。エラーの場合、システムは問題の説明とともにapplication(_:didFailToRegisterForRemoteNotificationsWithError:)を呼び出します:証明書の設定ミス、ネットワークの利用不可、またはプロジェクトの設定ミス。
トークンを受信した後、アプリはデータベースに保存するためにすぐにサーバーに送信する必要があります。APIリクエストには、トークン、デバイス識別子(マッピング用)、環境(sandbox/production)、オプションで追加データ(OSバージョン、デバイスモデル、言語)が含まれます。サーバーが常に最新のトークンを保持できるように、アプリの起動ごとにトークンを再送信することをお勧めします。
// 許可のリクエストとAPNSへの登録
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) {
[weak self] granted, error in
guard granted else {
print("許可が得られませんでした")
return
}
DispatchQueue.main.async {
UIApplication.shared
.registerForRemoteNotifications()
}
}
}
// APNSからDevice Tokenを取得
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenString = deviceToken
.map { String(format: "%02.2hhx", $0) }
.joined()
print("Device Token: \(tokenString)")
// サーバーにトークンを送信
PushTokenService.shared
.sendTokenToServer(tokenString) { success in
if success {
UserDefaults.standard.set(tokenString,
forKey: "lastDeviceToken")
}
}
}
プッシュシステムのサーバー側は、Device Tokenをデータベースに保存し、ユーザーと環境に関連付ける必要があります。通知を送信する際、サーバーはAPNSへのリクエストを作成し、URLにトークンと認証用のJWTトークン(または証明書)を含めます。適切なトークン管理は、プッシュ通知の配信率に重大な影響を与えます。
サーバー上のトークンテーブルには、少なくとも次のものが含まれている必要があります:Device Token(一意)、ユーザーID、環境(sandbox/production)、最終更新日、ステータス(アクティブ/非アクティブ)。送信時の高速検索のためにトークンに、ユーザーの全デバイスのリストを取得するためにユーザーにインデックスを追加することをお勧めします。多くのアプリでは、1人のユーザーが複数のデバイスを持つことができ、それぞれに独自のトークンがあります。
プッシュ通知を送信するために、サーバーは2つの方法でAPNSへのリクエストを認証する必要があります。証明書ベースは、Apple Developer Consoleで生成されたSSL証明書を使用します。トークンベースは、.p8キーを持つJWT(JSON Web Token)を使用し、証明書を更新することなく最大30日間有効です。トークンベースの認証はより現代的で、新しいプロジェクトにはAppleが推奨しています。
APNSへのリクエストには、HTTP/2 POSTメソッド、パス/3/device/{device_token}を含むURL、認証ヘッダー、ペイロードを含むJSONボディが含まれます。apns-topicヘッダーにはアプリのバンドルIDが含まれている必要があります。apns-priorityは配信優先度を示します(5 — 即時、10 — バッテリー節約)。apns-expirationは、APNSが通知の配信を試みるエポックからの秒数を設定します。
// APNS HTTP/2経由でNode.jsでプッシュを送信する例
const http2 = require('http2');
const client = http2.connect('https://api.push.apple.com');
const deviceToken = 'abcdef0123456789...';
const payload = JSON.stringify({
"aps": { "alert": "Hello!", "sound": "default" }
});
const req = client.request({
':method': 'POST',
':path': `/3/device/${deviceToken}`,
'apns-topic': 'com.example.app',
'apns-priority': '10',
'apns-expiration': '0',
'authorization': `bearer ${jwtToken}`
});
req.write(payload);
req.end();
req.on('response', (headers) => {
if (headers[':status'] === '200') {
console.log('プッシュが正常に送信されました');
}
});
多数のデバイスにプッシュ通知を送信する場合は、レート制御付きのバッチ送信を使用します。APNSは接続あたり毎秒1500リクエストを超えないことを推奨しています。制限を超えると、Appleサーバーは429 Too Many Requestsエラーを返します。大規模なキャンペーンでは、複数の接続を使用し、デバイス間で負荷を均等に分散します。
Device Tokenは永続的ではなく、いくつかのシナリオで変更される可能性があり、サーバー側に更新メカニズムが必要です。サーバーが古いトークンにプッシュを送信し続けると、APNSは410 Goneエラーを返し、その環境ではトークンが無効であることを示します。
Appleは、Device Tokenが変更されるいくつかのシナリオを文書化しています:ユーザーがアプリを再インストールする、iCloudバックアップからデバイスを復元する、新しいiOSバージョンをインストールする、またはネットワークやプライバシー設定をリセットする。各ケースで、アプリは次回起動時にAPNSから新しいトークンを受け取ります。サーバーはデータベース内のトークンを更新し、古いものを削除して新しいものを保存する必要があります。
サーバーが古いトークンにプッシュを送信すると、APNSはapns-unless-timestampヘッダーとともにHTTP 410を返します。このヘッダーは、トークンが無効になった時間を示します。サーバーはデータベース内のこのトークンを直ちに削除または無効化して、再送信を防ぐ必要があります。410エラーを無視すると、リソースが無駄になり、配信可能性率が低下します。
トークンデータベースを最新の状態に保つために、定期的なクリーンアップを実行することをお勧めします。クリーンアップスクリプトは、過去N日間のAPNSログを分析し、410エラーを受け取ったすべてのトークンを見つけて、データベースで無効化します。さらに、90日以上ユーザーアクティビティがないトークンは削除できます。これらはデータベースのサイズを増やすだけの無駄なレコードです。
プッシュ通知(ニュースレター、プロモーションキャンペーン)の一斉送信前に、トークンを事前検証することをお勧めします。APNSはバッチトークン検証のための直接APIを提供していないため、低優先度でテストプッシュを送信し、エラーを分析する戦略が使用されます。410エラーを返すトークンは、メインの送信から除外されます。
SwiftでDevice Tokenを取得する完全なサイクルを、エラー処理とサーバーへの送信を含めて見てみましょう。コードは以下をカバーしています:許可のリクエスト、APNSへの登録、Dataから16進文字列への変換、エラー処理、失敗時の再試行を含む独自サーバーへのトークン送信。
import UIKit
import UserNotifications
final class PushNotificationManager: NSObject {
static let shared = PushNotificationManager()
private let apiClient = APIClient()
private var currentToken: String?
func register() {
UNUserNotificationCenter.current()
.requestAuthorization(
options: [.alert, .badge, .sound]) {
[weak self] granted, error in
guard granted else {
Analytics.log(
"Push permission denied")
return
}
DispatchQueue.main.async {
UIApplication.shared
.registerForRemoteNotifications()
}
}
}
func handleDeviceToken(_ tokenData: Data) {
let token = tokenData
.map { String(format: "%02.2hhx", $0) }
.joined()
guard token != currentToken else { return }
currentToken = token
sendTokenToServer(token)
}
func handleRegistrationError(_ error: Error) {
Analytics.log(
"Push registration failed: \(error)")
// ネットワークエラー時の遅延後の再試行
if let urlError = error as? URLError,
urlError.code == .notConnectedToInternet {
DispatchQueue.main.asyncAfter(
deadline: .now() + 10) { [weak self] in
self?.register()
}
}
}
private func sendTokenToServer(_ token: String) {
let body = PushTokenRequest(
token: token,
environment: Environment.current == .debug
? "sandbox" : "production",
osVersion: UIDevice.current.systemVersion,
locale: Locale.current.identifier
)
apiClient.sendToken(body) { [weak self] result in
if case .success = result {
self?.currentToken = token
}
}
}
}
APNS登録時のエラーは、さまざまな理由で発生する可能性があります。最も一般的なものには、ネットワークの利用不可、Xcodeでの証明書の設定ミス(例:Push Notifications機能が無効)、シミュレーターの使用(プッシュをサポートしていない)、または不正なプロビジョニングプロファイルが含まれます。本番環境では、エラーをログに記録し、可能であれば次回のアプリ起動時に登録を再試行することが重要です。
iOSシミュレーターは実際のDevice Tokenの受信をサポートしていません。シミュレーターでの登録をテストするには、i386アーキテクチャチェックを使用します。デバッグビルドでは、トークンの取得をシミュレートするか、モックオブジェクトを使用したUIテストを使用できます。実際のプッシュ通知のテストは常にXcodeに接続された物理デバイスで行われます。
よくある質問
はい、Device Tokenはアプリの再インストール、バックアップからのデバイス復元、またはiOSのアップデート時に変更される可能性があります。サーバーはトークンの更新を処理する必要があります。既知のデバイスから新しいトークンを受信したら古いものを置き換え、410エラーが発生したらデータベースからトークンを削除します。
Device Tokenは、小文字(0–9、a–f)の64文字の32バイト16進文字列です。例:「a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2」。トークンはAPNSからDataとして渡され、アプリ側で文字列に変換されます。
サンドボックストークンは開発プロビジョニングプロファイルでビルドされたアプリに発行され、api.sandbox.push.apple.comでのみ機能します。プロダクショントークンはApp StoreとTestFlight用で、api.push.apple.comで機能します。サーバーは環境を区別し、適切なAPNSエンドポイントにプッシュを送信する必要があります。
410 Goneエラーは、Device Tokenが無効であることを意味します。サーバーはデータベースからこのトークンを直ちに削除し、送信試行を停止する必要があります。応答のapns-unless-timestampヘッダーは、トークンが機能しなくなった時間を示します。
AppDelegateのデリゲートメソッドapplication(_:didRegisterForRemoteNotificationsWithDeviceToken:)を確認します。メソッドが呼び出されれば、トークンは受信されています。デバッグログまたはOSLogを使用して、Xcodeコンソールにトークンを出力します。物理デバイスで、Network Link Conditionerを使用してトークンがサーバーに送信されていることを確認します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。