アプリケーション開発ポータルサイト
ServerNote.NET
Amazon.co.jpでPC関連商品タイムセール開催中!
カテゴリー【iPhone/iPadMacOSGoogleSwift
FirebaseでiOSアプリにプッシュ通知機能を実装する【2】
POSTED BY
2024-03-15
FirebaseでiOSアプリにプッシュ通知機能を実装する【1】

続きです。通知通信のための証明書作成・登録はテスト・本番用それぞれ前回で終えたので、あとは段階を踏んで実装・テストするだけです。

Firebase SDKにてCloud Messagingの使用をオンにする

Podfileに追記します。

pod 'FirebaseMessaging'

アップデート&インストールします。

pod install --repo-update

これでソース中でimport FirebaseMessagingとして、コードを書けるようになるはずです。

CapabilityにPush NotificationsとBackground Modesを追加する

Xcodeでプロジェクト(xcworkspace)を開いて、左ペイン一番上プロジェクト名青アイコン→TARGETS→MyAppで、「Signing & Capabilities」を開きます。

気づきにくいですが左上あたりに「+Capability」があるので、ここで「Push Notifications」と「Background Modes」をそれぞれ追加します。そして「Background Modes」には、「Remote notifications」をチェックします。

プッシュ通知に対応するSwiftコードを書く

基本的にはAppDelegate.swiftに書きますが、ユーザーに通知の許可をもらうダイアログはアプリの他の適切な箇所のほうが良いです。

SwiftAppDelegatePushNotify.swiftGitHub Source
import SwiftUI
import FirebaseCore
import FirebaseMessaging
import UserNotifications

class AppDelegate: NSObject, UIApplicationDelegate {
    let gcmMessageIDKey = "gcm.message_id"
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions
                     launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("AppDelegate.application")
        FirebaseApp.configure()
        
        Messaging.messaging().delegate = self
        UNUserNotificationCenter.current().delegate = self
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { _, _ in }
        )
        
        application.registerForRemoteNotifications()
        //application.applicationIconBadgeNumber = 0
        
        return true
    }
    
    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        print("AppDelegate.didReceiveRemoteNotification")
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }
        print(userInfo)
    }
    
    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
    -> UIBackgroundFetchResult {
        print("AppDelegate.didReceiveRemoteNotificationBackground")
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }
        print(userInfo)
        return UIBackgroundFetchResult.newData
    }
    
    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("AppDelegate.didFailToRegisterForRemoteNotificationsWithError,error=\(error.localizedDescription)")
    }
    
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken,deviceToken=\(deviceToken)")
    }
}

// [START ios_10_message_handling]
extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification) async
    -> UNNotificationPresentationOptions {
        print("AppDelegate.UNUserNotificationCenterDelegate.willPresent")
        let userInfo = notification.request.content.userInfo
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }
        print(userInfo)
        return [[.banner, .badge, .sound]]
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse) async {
        print("AppDelegate.UNUserNotificationCenterDelegate.didReceive")
        let userInfo = response.notification.request.content.userInfo
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }
        print(userInfo)
    }
}
// [END ios_10_message_handling]

extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("AppDelegate.MessagingDelegate.didReceiveRegistrationToken,fcmToken=\(String(describing: fcmToken))")
        let dataDict: [String: String] = ["token": fcmToken ?? ""]
        NotificationCenter.default.post(
            name: Notification.Name("FCMToken"),
            object: nil,
            userInfo: dataDict
        )
    }
}

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

ここではアプリ起動時にrequestAuthorizationしてユーザーに許可を促しています。

テストデバイストークンを取得してコピーしておく

このコードでアプリを実行すると、

print("AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken,deviceToken=\(deviceToken)")

または

print("AppDelegate.MessagingDelegate.didReceiveRegistrationToken,fcmToken=\(String(describing: fcmToken))")

が呼ばれてそのデバイスのトークン文字列がデバッグエリアに出力されますので、それをコピーしておきます。

Firebase Messagingでテストメッセージを送信する

Firebaseコンソールを開いて、左ペインの「Messaging」を開き、Messagingのメイン画面にて「新しいキャンペーンを作成→通知」を開きます。

・端末上に表示される通知のタイトル、通知テキスト(本文)を入力します。
・「ターゲット」で、通知を送信するターゲットアプリを選択します。jp.co.mycorp.MyApp。
・「スケジュール設定」は今すぐ送信「現在」
・「その他のオプション」で通知音の有無、バッジの有無と数を指定できます。バッジありで数を指定した場合、アプリ側のアイコンの右上に未読の数が赤丸で出るあれです。

ここまで設定を終えたら「確認」ボタンを押さずに、「通知」に戻って「テスト メッセージの送信」を押します。ここで、「FCM 登録トークンを追加」とあるので、さきほど控えておいたデバイスのトークン文字列を貼り付けて登録し、チェックで選択して、「テスト」ボタンを押すと、即座に実行中のデバイス単体に通知が送信されます。

通知をタップすれば上記コードのAppDelegate.UNUserNotificationCenterDelegate.didReceiveが呼ばれますし、アプリが実行中で表示中であればAppDelegate.UNUserNotificationCenterDelegate.willPresentが呼ばれるはずです。そうなれば成功です。

※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!
ご連絡は以下アドレスまでお願いします★

☆ServerNote.NETショッピング↓
ShoppingNote / Amazon.co.jp
☆お仲間ブログ↓
一人社長の不動産業務日誌
【キーワード検索】