ローカル通知とは、リモートサーバーを介さずにアプリがユーザーに送信するメッセージです。すべてのデータは受信者のデバイス上で直接処理され表示されます。この仕組みは、アプリがバックグラウンドにあるか閉じられている場合のリマインダー、タイマー、アラームに適しています。Apple Developer Documentationによると、UNUserNotificationCenterはiOSでローカル通知の一元管理を提供します。
重要なポイント
ローカル通知は、アプリがインストールされている同じデバイス上でオペレーティングシステムによって生成および表示されるトリガーメッセージです。プッシュ通知とは異なり、ローカル通知は外部サーバーを経由しません — すべてのスケジューリングロジックはクライアント上で実行されます。
このような通知は、アプリの状態(アクティブ、最小化、完全に閉じている)に関係なく機能します。オペレーティングシステムがスケジュールされた時間に配信を処理し、開発者はコンテンツとトリガーのみを指定します。
システムはネットワークがなくてもローカル通知の配信を保証します。これは、安定したインターネット接続と稼働中のサーバーを必要とするプッシュ通知に対する重要な利点です。
各ローカル通知は、コンテンツ(タイトル、本文、サウンド)、トリガー(時間または地理的条件)、リクエスト識別子の3つの部分で構成されます。識別子を使用すると、配信前に通知をキャンセルまたは更新できます。
開発者はiOSでアプリごとに最大64個のローカル通知をスケジュールでき、Androidでは無制限です。この違いはオペレーティングシステムのアーキテクチャ上の制約によるものです。
両方のプラットフォームは、ローカル通知を処理するための独自のAPIを提供しています。iOSでは中心的なコンポーネントはUNUserNotificationCenter、AndroidではNotificationManagerです。インターフェースは異なりますが、ロジックは同じです:アプリがリクエストを作成し、システムに登録し、OSがスケジュールされた時間に通知を配信します。
iOSはカレンダーイベントにUNCalendarNotificationTrigger、間隔にUNTimeIntervalNotificationTrigger、地理位置情報にUNLocationNotificationTriggerを使用します。AndroidはAlarmManager、WorkManager、およびsetExactによる正確なスケジューリングを提供します。
Android 12以降 — SCHEDULE_EXACT_ALARMにはユーザーからの特別な許可が必要です。iOSでは、UNUserNotificationCenter.requestAuthorizationを通じて一度許可が求められ、ユーザーがアクセスレベル(バナー、サウンド、バッジ)を選択します。
ローカル通知は、コンテンツではなくトリガータイプによって分類されます。各タイプは、いつ、どのような条件で通知がユーザーに表示されるかを決定します。
iOSとAndroidでは、トリガータイプの実装は異なりますが、論理的な分類は同じです。iOSは日付にUNCalendarNotificationTrigger、間隔にUNTimeIntervalNotificationTrigger、地理位置情報にUNLocationNotificationTriggerを使用します。AndroidはsetExactとsetRepeatingを備えたAlarmManager、および遅延タスク用のWorkManagerを提供します。
| トリガータイプ | 説明 | 例 |
|---|---|---|
| 時間間隔 | 起動からN秒後に通知 | カウントダウンタイマー |
| カレンダー日付 | 特定の日時に通知 | 会議のリマインダー |
| 地理位置情報 | 領域への出入り時に通知 | 店舗でのリマインダー |
| 即時 | API呼び出し時に即時配信 | ダウンロード通知 |
iOSはUNNotificationAttachmentもサポートしています — 画像、オーディオ、またはビデオを通知本文に添付します。AndroidはNotificationCompat.Styleを介してボタンと大きな画像を備えたカスタムテンプレートをサポートしています。
トリガーの選択はシナリオによって異なります:カレンダーのリマインダーにはカレンダートリガーが最適で、地理的リマインダーには地理位置情報が最適です。間隔トリガーは固定期間の定期的なイベントに適しています。
iOSでは、アプリが閉じられていてもローカル通知はシステムによって配信されます — UNUserNotificationCenterが独立してキューを管理します。Androidでは、配信は選択されたメカニズムに依存します:AlarmManagerは画面がオフでも作動しますが、WorkManagerは省電力を考慮します。
ローカル通知は、外部インフラが過剰または利用できないタスクを解決します。主なシナリオ:リマインダー、タイマー、オンボーディングのヒント、遅延アクション。
Localyticsの調査によると、ローカルリマインダーを使用するアプリは、インストール後最初の1週間で35%多くのユーザーを維持します。これにより、ローカル通知は強力なオンボーディングツールになります。
頻度を乱用しないことが重要です — システムは同じアプリからの通知を自動的にグループ化し、ユーザーは迷惑になった場合にすべてのローカル通知を無効にできます。最適な頻度は、重要でないイベントに対して1日あたり2〜3件以内です。
Androidでローカル通知をスケジュールするには、AlarmManagerとともにNotificationManagerを使用します。Android 8+では、最初に通知チャネルを作成する必要があります。そうしないと通知が表示されません。
val channelId = "reminder_channel"
val notificationId = "task_reminder_42"
val channel = NotificationChannel(
channelId,
"リマインダー",
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "タスクリマインダー用チャネル"
}
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
val intent = Intent(this, ReminderReceiver::class.java).apply {
putExtra("notification_id", notificationId)
putExtra("channel_id", channelId)
}
val pendingIntent = PendingIntent.getBroadcast(
this, notificationId.hashCode(),
intent, PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = getSystemService(AlarmManager::class.java)
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
triggerTimeMillis,
pendingIntent
)
Android 12+では、setExactを呼び出す前にSCHEDULE_EXACT_ALARM許可を確認してください。許可が付与されていない場合は、時間枠内での配信を保証するsetWindowを使用してください。
AlarmManagerが作動すると、システムはBroadcastReceiverが受信するブロードキャストIntentを送信します。その中で、NotificationManagerを介して通知を作成して表示する必要があります。PendingIntentがFLAG_UPDATE_CURRENTを使用していることを確認してください。そうしないと、データが変更されたときに古い通知が古いIntentを使い続けます。
iOSでは、ローカル通知はUNUserNotificationCenterを介してUNMutableNotificationContentといずれかのトリガーを使用して作成されます。スケジューリングの前に、ユーザーから許可を取得する必要があります。
import UserNotifications
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
guard granted else { return }
}
let content = UNMutableNotificationContent()
content.title = "タスクリマインダー"
content.body = "18:00までにレポートを完了するのを忘れないでください"
content.sound = .default
content.userInfo = ["task_id": "42"]
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 3600,
repeats: false
)
let request = UNNotificationRequest(
identifier: "task_reminder_42",
content: content,
trigger: trigger
)
center.add(request)
iOSは最大64件の同時ローカル通知リクエストをサポートしています。制限を超えると、アクティブなリクエストが配信またはキャンセルされるまで、システムは新しいリクエストを拒否します。現在のキューを確認するにはgetPendingNotificationRequestsを使用してください。
ユーザーがiOSでローカル通知と対話すると、UNUserNotificationCenterDelegateのuserNotificationCenter:didReceive responseメソッドが呼び出されます。このメソッドは、リクエスト識別子、actionIdentifier(どのボタンが押されたか)、カスタムuserInfoを提供します。これにより、単純な通知のオープンと特定のアクションボタンの押下を区別できます。
ローカル通知を便利で迷惑にならないようにするには、いくつかの重要なルールに従ってください。第一に:頻度を制御する — 重要でないイベントでは1日2〜3件以内に抑え、そうしないとユーザーがすべてのアプリ通知を無効にしてしまいます。
第二に:ユーザーに選択肢を与えてください。特定のタイプのローカル通知を無効にする機能をインターフェースに追加します。Androidでは、重要度の低い別個のNotificationChannelを使用します。iOSでは、アプリ設定で別個のカテゴリを使用します。
第三に:コンテキストの関連性 — 通知はユーザーが必要とするときに表示されるべきです。地理的トリガーは自宅近くのリマインダーに最適で、カレンダートリガーは会議に、間隔トリガーは水分補給やストレッチなどの定期的な活動に適しています。不必要にタイプを混在させないでください。
第四に:実際のデバイスでテストしてください。iOSシミュレーターは、特にバックグラウンドでのローカル通知配信のすべてのシナリオをエミュレートするわけではありません。Androidでは、adb shell dumpsys notificationを使用して、スケジュールされた通知のキューとそのパラメーターを確認してください。第五に:アプリのインターフェースを通じて通知を無効にする機能を常にユーザーに提供してください — これはUXおよびApp Store Review Guidelinesの必須要件です。
よくある質問
ローカル通知はサーバーを介さずにデバイスがスケジュールして配信します。プッシュ通知は外部サービス(FCM、APNS)とインターネット接続が必要です。ローカル通知はオフラインでも動作しますが、プッシュはネットワークアクセスが必要です。
iOSは同時に64件のスケジュール済みリクエストに制限しています。Androidには厳格な制限はありませんが、500件を超える通知はシステムパフォーマンスを低下させ、配信時間に影響を与える可能性があります。
はい、iOSではリクエスト識別子を指定してremovePendingNotificationRequestsを使用します。Androidでは、NotificationManager.cancelを呼び出すか、AlarmManagerを介してPendingIntentをキャンセルします。キャンセルには一意の識別子が必要です。
iOSでは、requestAuthorizationによる許可が必須です。Android 13+(Tiramisu)でも、POST_NOTIFICATIONS許可が必要です。古いバージョンのAndroidでは、ローカル通知に明示的な許可は必要ありません。
iOSでは、UNNotificationActionを作成してUNNotificationCategoryに追加します。Androidでは、BroadcastReceiverをターゲットとするPendingIntentとともにNotificationCompat.Builder.addActionを使用します。各ボタンはアプリ内で個別のアクションをトリガーします。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。