【发布时间】:2020-01-08 09:10:31
【问题描述】:
我是 iOS/Swift 新手,无法让推送通知正常工作。我已将服务器后端配置为在发生某些操作时将通知推送到我的应用程序。我已经通过 FCM 配置了数据通知,因为我需要通知中的一些自定义数据来打开一个活动/视图或另一个。这是用于发送通知的代码(python/django):
registration_id = profiletarget.device_token
message_title = "Ha llegado tu turno"
message_body = "Entra y escribe en el relato para el que estás en cola"
data_message = {
"title" : "¿Listo para escribir?",
"body" : "Ha llegado tu turno para escribir en el relato. Recuerda que tienes un minuto para aceptar tu turno y 3 para escribir.",
"bookid" : booktarget.pk,
"multimediaurl" : multimediaused.url
}
result = push_service.notify_single_device(registration_id=registration_id, data_message=data_message)
此代码中的所有内容都正常工作,因为我在 Android 上正确获取了它们。但在 iOS 上...我无法正常工作。
我已获得通知令牌,已将其发布到我的服务器,我已使用 FCM 控制台上的通知发送器发送测试推送通知(iPhone 获取它们),但不是来自我的自定义方法的通知,它没有什么都不显示。服务器方法有什么问题还是我遗漏了什么?
这是快速代码:
import UIKit
import KeychainSwift
import Firebase
import FirebaseMessaging
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
var window : UIWindow?;
var storyboard : UIStoryboard?;
var token = ""
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
self.storyboard = UIStoryboard(name: "Main", bundle: Bundle.main);
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: UIFont(name: "PT Sans", size: 12)!], for: .normal)
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: UIFont(name: "PT sans", size: 12)!], for: .selected)
let keychain = KeychainSwift()
token = keychain.get("token") ?? ""
if (token != ""){
print("log-token: ", token)
print("log-redirection: ", "no redirection needed!")
FirebaseApp.configure()
Messaging.messaging().delegate = self
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
} else {
print("log-token: ", "noToken")
print("log-redirection: ", "redirection to LoginController")
window?.rootViewController = self.storyboard?.instantiateViewController(withIdentifier: "loginView");
}
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
postNotificationToken(token: token)
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
let dataDict:[String: String] = ["token": fcmToken]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
func postNotificationToken(token:String) {
var request = URLRequest(url: URL(string: "https://myurl?myparam="+token)!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer "+self.token, forHTTPHeaderField: "myauth")
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
let httpURLResponse = response as? HTTPURLResponse;
if (httpURLResponse?.statusCode == 200){
let string = String.init(data: data!, encoding: String.Encoding.utf8)
print(string)
} else {
print(httpURLResponse?.statusCode)
}
})
task.resume()
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Received data message: \(remoteMessage.appData)")
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
// MARK: UISceneSession Lifecycle
}
这是我的目标能力:
这是我的开发者帐户中用于 APN 通知的密钥:
使用 FCM 控制台,通知正常:
感谢您阅读这篇长文。任何事情都会有帮助!
【问题讨论】:
-
好吧,您的方法已命名为
func postNotificationToken(token:String),并且您写道“我已将其发布到我的服务器”,但我看到了request.httpMethod = "GET"。这让我很困扰。 -
是的,我写“post”不是http方法,我只是说它是send的同义词。令牌通过 get 请求作为 url 中的参数发送到服务器。并且令牌已正确存储在数据库中(我已检查它在 xcode 打印和数据库中是否相同)
-
是的,GoogleService-info.plist 在项目中,并且推送通知已添加到功能中。正如我在帖子中所说,来自 FCM 控制台的默认测试通知可以正常工作(所以它会接收它)......不起作用的是我的自定义通知
-
您创建的推送通知证书可能有问题。或者当您将该证书添加到 FCM 中的项目时可能出现问题。建议通过直接从 FCM 控制台发送通知来调试/测试它。如果这确实有效,那么问题出在您的服务器代码上,否则重新创建推送 cer。并再次将其添加到 FCM 项目中。
-
您好,谢谢。正如我所说,设置 FCM 控制台通知工作正常,但我无法让它与我的自定义通知一起工作(适用于 android),使用自定义通知在 iphone 上没有收到任何内容,但 FCM 控制台一切正常。
标签: python ios swift django firebase-cloud-messaging