firebaseAuth/FCMなどでFirebaseを実装し、Firebase Consoleから通知を正常に送信しました。
しかし、私は自分のアプリサーバーから通知をプッシュする必要があります。
デバイスの登録IDを取得する正しい方法は次のとおりです:-
1)didRegisterForRemoteNotificationWithDeviceTokenから登録IDトークンを取得
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token += String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
print("Registration succeeded!")
print("Token: ", token)
Callquery(token)
}
2)firebaseから登録トークンを取得(現在の登録トークンを取得するFirebaseドキュメントに基づく)
let token = FIRInstanceID.instanceID().token()!
私は最初の方法を使用していましたが、登録IDがそれに応じてアプリサーバーデータベースに保存されていてもプッシュ通知が受信されず、このCURLセッションの結果が表示されます:-
{"multicast_id":6074293608087656831,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
私はまた、2番目の方法を試し、以下のようにアプリを実行中に致命的なエラーが発生しました:-
誰かが私に正しい方法を教えてくれれば感謝します!
tokenRefreshNotification
関数は、アプリの起動時に常に呼び出されるとは限りません。
ただし、通常のdidRegisterForRemoteNotificationsWithDeviceToken
デリゲート関数内にコードを配置すると、毎回トークンを取得できます。
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
}
(Swift 3 + Firebase 4.0.4)
static var FirebaseToken : String? {
return InstanceID.instanceID().token()
}
Firebaseが推奨する方法:
let token = Messaging.messaging().fcmToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
InstanceID.instanceID().instanceID(handler: { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
})
}
Swift 4
礼儀: https://stackoverflow.com/a/50945350/1014164
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
FCMデバイストークンSwift
let fcmDeviceToken = FIRInstanceID.instanceID().token()
print("FCM token: \(fcmDeviceToken ?? "")")
Firebaseトークン更新通知の最初の登録:
NotificationCenter.default.addObserver(self, selector:
#selector(tokenRefreshNotification), name:
NSNotification.Name.InstanceIDTokenRefresh, object: nil)
その後、tokenRefreshNotificationセレクターでトークンを受信できます。
func tokenRefreshNotification(_ notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
2番目のオプションを使用すると、これは本当に愚かでシンプルに見えますが、そのnilのオプションの致命的なエラーを修正するには、最後のforce-unwrapを削除するだけです
あなたのコード:var token = FIRInstanceID.instanceID().token()!
成功する:var token = FIRInstanceID.instanceID().token()
それは少なくともその厄介なクラッシュを修正します
私は同じ問題を抱えていましたが、何が起こっているのか理解できませんでした。
@Samによって提案されたdidRegisterForRemoteNotificationsWithDeviceToken
は(ほぼ)毎回呼び出されるため、回避策として適しています。ただし、更新されたトークンでアプリを初めて開いたときには呼び出されません。
したがって、このシナリオでは次のものが必要です。
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Refreshed Token: \(fcmToken)")
}
したがって、次のもののみを使用する場合:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let fcmToken = InstanceID.instanceID().token() {
print("InstanceID token: \(fcmToken)")
}
}
ユーザーがアプリを2回開いたときにのみ、「更新されたトークン」を取得します。
アプリをアンインストールし、ビルドフォルダーをクリーンアップすることで(製品>ビルドフォルダーのクリーン)、更新トークンを強制的に管理しました。テストに適しています。
理想的には、messaging:didReceiveRegistrationToken
デリゲートメソッドですべて処理できますが、動作させることはできませんでした。 FCMトークンの変更を通知する別の方法は、ドキュメントで提案されているNSNotification
という名前のkFIRMessagingRegistrationTokenRefreshNotification
をリッスンすることです。 https://firebase.google.com/docs/cloud-messaging/ios/client
最初に次のようなライブラリをインポートします。
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
デリゲートの設定:MessagingDelegate、UNUserNotificationCenterDelegate
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
DidFinishLaunching()でこのコードを記述します。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
Messaging.messaging().delegate = self
//remote Notifications
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (isGranted, err) in
if err != nil {
//Something bad happend
} else {
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
} else {
// Fallback on earlier versions
}
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge,.sound,.alert], completionHandler: { (granted, error) in
application.registerForRemoteNotifications()
})
}else{
let notificationSettings = UIUserNotificationSettings(types: [.badge,.sound,.alert], categories: nil)
UIApplication.shared.registerUserNotificationSettings(notificationSettings)
UIApplication.shared.registerForRemoteNotifications()
}
return true
}
このようにconnectFCMメソッドを記述します。
func ConnectToFCM() {
Messaging.messaging().shouldEstablishDirectChannel = true
if let token = InstanceID.instanceID().token() {
print("\n\n\n\n\n\n\n\n\n\n ====== TOKEN DCS: " + token)
}
また、プッシュ通知を登録および受信するためのデリゲートメソッドを記述します。
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("\n\n\n\n\n ==== FCM Token: ",fcmToken)
HelperFunction.helper.storeInUserDefaultForKey(name: kFCMToken, val: fcmToken)
ConnectToFCM()
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// UIApplication.shared.applicationIconBadgeNumber += 1
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Barker"), object: nil)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
}
100%動作し、簡単でテスト済み
注:1)xcodeの機能セクションからのプッシュ通知を有効にします。
2)firebaseプロジェクト設定にアップロードされた両方のp12証明書を2回確認します。
3)デバイストークンは、シミュレータではなく実際のデバイスからのみ取得できます。
現在のFCMトークンを取得するには
if let token = Messaging.messaging().fcmToken {
// token is current fcmToken
}
現在のFCMトークンを更新するには
現在のinstanceIdを削除すると、新しいトークンはすぐにMessagingDelegate(messaging:didReceiveRegistrationToken)で受信されます。
InstanceID.instanceID().deleteID { (error) in
if let er = error {
print(er.localizedDescription)
} else {
print("instanceID().deleteID success ---------------➤")
}
}