使用Firebase和PHP在iOS中实现推送通知

4

我对开发非常陌生,无法找到关于这个主题的完整支持。我尽力使用Firebase帮助页面。但我无法在iOS设备上接收通知,但FCM在Android上运行得非常完美。

这是我的Xcode appdelegate:

import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UIApplication.shared.applicationIconBadgeNumber = 0
        // Override point for customization after application launch.
        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 })

            // For iOS 10 data message (sent via FCM)
            //FIRMessaging.messaging().remoteMessageDelegate = self

        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            UIApplication.shared.registerUserNotificationSettings(settings)
            UIApplication.shared.registerForRemoteNotifications()
        }

        application.registerForRemoteNotifications()

        FirebaseApp.configure()
        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token1 = Messaging.messaging().fcmToken
        print("FCM token: \(token1 ?? "")")
        var request = URLRequest(url: URL(string: "http://www.myurl.com/register.php")!)
        request.httpMethod = "POST"
        let postString = "Token="+token1!
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {                                                 // check for fundamental networking error
                print("error=\(String(describing: error))")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }

            let responseString = String(data: data, encoding: .utf8)
            print("responseString = \(String(describing: responseString))")
        }
        task.resume()
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Registration failed!")
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter,  willPresent notification: UNNotification, withCompletionHandler   completionHandler: @escaping (_ options:   UNNotificationPresentationOptions) -> Void) {

        // custom code to handle push while app is in the foreground
        print("Handle push from foreground\(notification.request.content.userInfo)")

        let dict = notification.request.content.userInfo["aps"] as! NSDictionary
        let d : [String : Any] = dict["alert"] as! [String : Any]
        let body : String = d["body"] as! String
        let title : String = d["title"] as! String
//        print("Title:\("FOSG NOTIFICATION") + body:\(body)")
        self.showAlertAppDelegate(title: "Federation Of Safety Glass",message:body,buttonTitle:"ok",window:self.window!)

    }

    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // if you set a member variable in didReceiveRemoteNotification, you  will know if this is from closed or background
        print("Handle push from background or closed\(response.notification.request.content.userInfo)")
    }

    func showAlertAppDelegate(title: String,message : String,buttonTitle: String,window: UIWindow){
        let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: buttonTitle, style: UIAlertActionStyle.default, handler: nil))
        window.rootViewController?.present(alert, animated: false, completion: nil)
    }
    // Firebase ended here

}

这是我在服务器端使用PHP编写的代码:

  $tokens = array(); $mess = '';
    // queries from db to set the values of variables.
    function send_notification ($tokens, $message)
    {
        $url = 'https://fcm.googleapis.com/fcm/send';
        $fields = array(
             'registration_ids' => $tokens,
             'data' => $message
            );
        $headers = array(
            'Authorization:key = **key ',
            'Content-Type: application/json'
            );
       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL, $url);
       curl_setopt($ch, CURLOPT_POST, true);
       curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);  
       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
       curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
       $result = curl_exec($ch);           
       if ($result === FALSE) {
           die('Curl failed: ' . curl_error($ch));
       }
       curl_close($ch);
       return $result;
    }
    $message = array(
        "body" => $mess,
        "message" => $mess,
        "title" => "FOSG NOTIFICATION",
        "sound" => 1,
        "vibrate" => 1,
        "badge" => 1,
    );
    $t = implode('',$tokens);
    if(t != '') $message_status = send_notification($tokens, $message);

请帮助我学习并解决我的问题


查看这个快速入门指南:https://github.com/firebase/quickstart-ios/tree/master/messaging 它帮助我设置了消息传送。然后尝试从Firebase控制台发送一条消息并确保它能正常工作。这将有助于缩小问题是Swift代码还是PHP的范围。 - Jen Person
谢谢你的回复,Jen。 我使用你提供的Github源代码找不到错误。 但是Firebase控制台成功地发送了通知,只有当我通过我的服务器脚本发送它们时,我才收不到任何东西。 - Sarabjit
我能想到的第一件事是您没有将正确的证书上传到Firebase。您可以尝试仔细检查一下。 - Dan Leonard
嗨,丹尼尔,我不确定这个想法是否正确,但如果我的证书有误,Firebase控制台不应该成功发送通知。 - Sarabjit
看这个链接: https://dev59.com/B1kS5IYBdhLWcg3wvI20 。也许将 'priority'=>'high'添加到 array 中对你有用呢? - Jen Person
1个回答

3

在发送JSON之前,只需更改字段名称即可。

更改以下内容:

$fields = array(
             'registration_ids' => $tokens,
             'data' => $message
            );

to

$fields = array(
             'registration_ids' => $tokens,
             'notification' => $message,
             'priority' => 'high'
            );

我也有类似的问题,我无法在IOS中接收数据消息,请确认是否有预定义的数据消息格式我想要在IOS中接收?是否有预定义的键需要使用?如果格式不正确,那么我将无法接收通知,这是真的吗? - Hafiz Shoaib Awan
将上面的代码中的"data"更改为"notification"。 - Sarabjit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接