如何在后台接收通知时显示警报和播放声音

时间:2018-02-21 17:28:12

标签: ios swift notifications firebase-cloud-messaging

我实施了这些程序,以便使用Firebase云消息传递服务。 我设置了

  

FirebaseAppDelegateProxyEnabled为NO(混合禁用)

因为我想使用结构" 数据"来自定义要发送到设备的消息而不是" 通知"结构体。 我可以从调试输出中看到在此回调中收到一条消息:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

// With swizzling disabled you must let Messaging know about the message, for Analytics
        Messaging.messaging().appDidReceiveMessage(userInfo)
            // Print message ID.
            if let messageID = userInfo[gcmMessageIDKey] {
                print("Message ID: \(messageID)")

        }

    // Print full message.
    print(userInfo)


    // I want to play a sound
    // create a sound ID, in this case its the SMSReceived sound.
    let systemSoundID: SystemSoundID = 1007 // file:// /System/Library/Audio/UISounds/sms-received1.caf
    // to play sound
    AudioServicesPlaySystemSound(systemSoundID)
    if let title = userInfo["title"] as? NSString {

          let myalert = MyAlert(title: "New message received!", message: title as String, preferredStyle: UIAlertControllerStyle.alert)

          myalert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
          myalert.addAction(UIAlertAction(title: "Open app", style: .default, handler: { _ in
          print("The \"OK\" alert occured.")
          }))
          self.window?.rootViewController?.present(myalert, animated: true, completion: nil)

    }// END if let title = alert["title"]

    completionHandler(UIBackgroundFetchResult.newData)
}

它在两种情况下都会提升(前后)。 一切都在前景完美,但在背景中没有声音和警报。 我很确定我错过了什么,但我无法理解...也许我需要一些"授权"从操作系统到显示和提醒和播放声音?

编辑1: 我实现了UNUserNotificationCenterDelegate以请求授权:

func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        FirebaseApp.configure()

        // [START set_messaging_delegate]
        Messaging.messaging().delegate = self
        // [END set_messaging_delegate]
        // Register for remote notifications. This shows a permission dialog on first run, to
        // show the dialog at a more appropriate time move this registration accordingly.
        // [START register_for_notifications]
        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()

        // [END register_for_notifications]

        if launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] != nil {
            // show alert
            let myalert = MyAlert(title: "New message!", message: "MyApp" as String, preferredStyle: UIAlertControllerStyle.alert)

            myalert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
            myalert.addAction(UIAlertAction(title: "Open MyApp", style: .default, handler: { _ in
                print("The \"OK\" alert occured.")
            }))
            self.window?.rootViewController?.present(myalert, animated: true, completion: nil)
        }


        return true
    }

1 个答案:

答案 0 :(得分:4)

解决了! 我使用内置系统和#34;通知"启用了调配的结构(info.plist中为FirebaseAppDelegateProxyEnabled = YES),这是我创建的json消息:

{
"message":
     {
          "topic":"topic",
          "notification":
               {
                    "body":"body",
                    "title":"title"
               },
          "apns":
               {
                    "payload":
                         {
                              "aps":
                                   {
                                        "sound":"default"
                                   }
                         }
               }
     }
}

这是我用过的AppDelegate.swift类......

import UIKit
import StoreKit
import UserNotifications
import Firebase
import AVFoundation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate,MessagingDelegate {



var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    self.registerForRemoteNotification()

    //Firebase initialization
    FirebaseApp.configure()
    // To receive registration tokens on app start we need to implement the messaging delegate protocol in
    // a class and provide it to the delegate property after calling FirebaseApp.Configure
    Messaging.messaging().delegate = self

    let token = Messaging.messaging().fcmToken
    print("FCM TOKEN = \(String(describing: token))")

    if let remote = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification]  as? [AnyHashable : Any] {
        self.sendToNewsPage()
    }

    return true
}

func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
    //
    print("Application didRegister notificationSettings")
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Disable swizzling, explicitly map the APNs token to the FCM registration token.
    //Messaging.messaging().apnsToken = deviceToken
    Messaging.messaging().subscribe(toTopic: "topic")
    print("Subcribed to topic")
}

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:.
}

// MARK: Remote Notifications
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
    #if DEBUG
        print(userInfo)
    #endif

    let state: UIApplicationState = UIApplication.shared.applicationState
      if state == .active {
        // create a sound ID, in this case its the SMSReceived sound.
        let systemSoundID: SystemSoundID = 1007
        // to play sound
        AudioServicesPlaySystemSound(systemSoundID)

        if let aps = userInfo["aps"] as? NSDictionary {
            if let alert = aps["alert"] as? NSDictionary {
                if let title = alert["title"] as? NSString {

                    let myalert = MyAlert(title: "New message received!", message: title as String, preferredStyle: UIAlertControllerStyle.alert)

                    myalert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
                    myalert.addAction(UIAlertAction(title: "Open ViewController", style: .default, handler: { _ in
                        print("The \"OK\" alert occured.")
                        self.sendToNewsPage()
                    }))
                    self.window?.rootViewController?.present(myalert, animated: true, completion: nil)

                }// END if let title = alert["title"]
            }// END if let alert = aps["alert"]
        }// END if let aps = userInfo["aps"]
    }// END else if state == .active
      else {
            self.sendToNewsPage()
    }
}

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {

    print("Firebase NEW registration token: \(fcmToken)")
    // Note: This callback is fired at each app startup and whenever a new token is generated.

}

func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
    print("Firebase registration token REFRESH: \(fcmToken)")

}

func registerForRemoteNotification()  {
    let application:UIApplication = UIApplication.shared

    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()

}

    // We need to implement this code only if swizzling id disabled - (FirebaseAppDelegateProxyEnabled = NO)
//    @available(iOS 10.0, *)
//    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
//
//        completionHandler([.alert, .badge, .sound])
//    }
//
//    @available(iOS 10.0, *)
//    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//
//        completionHandler()
//    }



//MARK : Notification

func sendToNewsPage() {
    let newsMessage = UIStoryboard(name: "MenuInfo", bundle: nil).instantiateViewController(withIdentifier: "SWRevealViewController")
    self.window?.rootViewController  = newsMessage
}

}

这个json让通知在后台发出声音!

相关问题