如何在应用未运行/ app时获得推送通知终止

我试过了
谷歌开发人员的“在iOS上安装GCM客户端应用程序”。
我的应用程序有安卓版本,服务器成功地向安卓发送推送通知。在iOS中,我可以将消息检索到didrecieveremotenotification函数。打印时如下所示:

aps: {
    alert =     {
        body = tyyy;
        title = "2 is going out at 03/24/2016 15:02:48";
    };
    badge = 2;
    sound = default;
}

当应用程序处于前台和后台时,它会收到此消息。当应用程序为后台时,系统托盘中不显示任何内容。
当应用程序终止,服务器发送推送通知时,我什么也没有收到,没有显示任何活动。
我的代码如下。
应用委托.swift
import UIKit

 @UIApplicationMain



class AppDelegate: UIResponder, UIApplicationDelegate, GGLInstanceIDDelegate,  GCMReceiverDelegate {

var window: UIWindow?

var connectedToGCM = false
var subscribedToTopic = false
var gcmSenderID: String?
var registrationToken = "AIzaSy-.....-11bSP6v72UvyKY"
var registrationOptions = [String: AnyObject]()

let registrationKey = "onRegistrationCompleted"
let messageKey = "onMessageReceived"
let subscriptionTopic = "/topics/global"


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")


    // Override point for customization after application launch.

    // [START_EXCLUDE]
    // Configure the Google context: parses the GoogleService-Info.plist, and initializes
    // the services that have entries in the file
    var configureError:NSError?
    GGLContext.sharedInstance().configureWithError(&configureError)
    assert(configureError == nil, "Error configuring Google services: \(configureError)")
    gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
    // [END_EXCLUDE]
    // Register for remote notifications
    if #available(iOS 8.0, *) {
        let settings: UIUserNotificationSettings =
        UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()
    } else {
        // Fallback
        let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
        application.registerForRemoteNotificationTypes(types)
    }

    // [END register_for_remote_notifications]
    // [START start_gcm_service]
    let gcmConfig = GCMConfig.defaultConfig()
    gcmConfig.receiverDelegate = self
    GCMService.sharedInstance().startWithConfig(gcmConfig)
    // [END start_gcm_service]

    application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],categories: nil))

    if let options = launchOptions {
        if let notification = options[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
            if let userInfo = notification.userInfo {

                // do something neat here
            }
        }
    }

    return true
}

func subscribeToTopic() {
    // If the app has a registration token and is connected to GCM, proceed to subscribe to the
    // topic
    if(registrationToken != "" && connectedToGCM) {
        GCMPubSub.sharedInstance().subscribeWithToken(self.registrationToken, topic: subscriptionTopic,
            options: nil, handler: {(error:NSError?) -> Void in
                if let error = error {
                    // Treat the "already subscribed" error more gently
                    if error.code == 3001 {
                        print("Already subscribed to \(self.subscriptionTopic)")
                    } else {
                        print("Subscription failed: \(error.localizedDescription)");
                    }
                } else {
                    self.subscribedToTopic = true;
                    NSLog("Subscribed to \(self.subscriptionTopic)");
                }
        })
    }
}

func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
    deviceToken: NSData ) {

        // [END receive_apns_token]
        // [START get_gcm_reg_token]
        // Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
        let instanceIDConfig = GGLInstanceIDConfig.defaultConfig()
        instanceIDConfig.delegate = self
        // Start the GGLInstanceID shared instance with that config and request a registration
        // token to enable reception of notifications
        GGLInstanceID.sharedInstance().startWithConfig(instanceIDConfig)
        registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
            kGGLInstanceIDAPNSServerTypeSandboxOption:true]
        GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
            scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
        // [END get_gcm_reg_token]


}

// [START receive_apns_token_error]
func application( application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
    error: NSError ) {
        print("Registration for remote notification failed with error: \(error.localizedDescription)")
        // [END receive_apns_token_error]
        let userInfo = ["error": error.localizedDescription]
        NSNotificationCenter.defaultCenter().postNotificationName(
            registrationKey, object: nil, userInfo: userInfo)
}


// [START ack_message_reception]
func application( application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
        print("Notification received: \(userInfo)")
        // This works only if the app started the GCM service
        GCMService.sharedInstance().appDidReceiveMessage(userInfo);
        // Handle the received message
        // [START_EXCLUDE]
        NSNotificationCenter.defaultCenter().postNotificationName("reloadTableEvent", object: nil)
        NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
            userInfo: userInfo)
        // [END_EXCLUDE]
}

func application( application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
    fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
        print("Notification received: \(userInfo)")
        // This works only if the app started the GCM service
        GCMService.sharedInstance().appDidReceiveMessage(userInfo);
        // Handle the received message
        // Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
        // [START_EXCLUDE]
        NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
            userInfo: userInfo)
        handler(UIBackgroundFetchResult.NoData);
        // [END_EXCLUDE]
}
// [END ack_message_reception]

func registrationHandler(registrationToken: String!, error: NSError!) {
    if (registrationToken != nil) {
        self.registrationToken = registrationToken
        print("Registration Token: \(registrationToken)")
        NSUserDefaults.standardUserDefaults().setValue(registrationToken, forKey: "registrationToken")
        self.subscribeToTopic()
        let userInfo = ["registrationToken": registrationToken]
        NSNotificationCenter.defaultCenter().postNotificationName(
            self.registrationKey, object: nil, userInfo: userInfo)
    } else {
        print("Registration to GCM failed with error: \(error.localizedDescription)")
        let userInfo = ["error": error.localizedDescription]
        NSNotificationCenter.defaultCenter().postNotificationName(
            self.registrationKey, object: nil, userInfo: userInfo)
    }
}

// [START on_token_refresh]
func onTokenRefresh() {
    // A rotation of the registration tokens is happening, so the app needs to request a new token.
    print("The GCM registration token needs to be changed.")
    GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
        scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}
// [END on_token_refresh]

// [START upstream_callbacks]
func willSendDataMessageWithID(messageID: String!, error: NSError!) {
    if (error != nil) {
        // Failed to send the message.
    } else {
        // Will send message, you can save the messageID to track the message
    }
}

func didSendDataMessageWithID(messageID: String!) {
    // Did successfully send message identified by messageID
}
// [END upstream_callbacks]

func didDeleteMessagesOnServer() {
    // Some messages sent to this device were deleted on the GCM server before reception, likely
    // because the TTL expired. The client should notify the app server of this, so that the app
    // server can resend those messages.
}

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 throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

func applicationDidEnterBackground(application: UIApplication) {

    NSUserDefaults.standardUserDefaults().setBool(false, forKey: "APP_RUNNING")

    // 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.

    GCMService.sharedInstance().disconnect()
    // [START_EXCLUDE]
    self.connectedToGCM = false
    // [END_EXCLUDE]
}

func applicationWillEnterForeground(application: UIApplication) {

    NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")

    // 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) {

    NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")

    // 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.

    // Connect to the GCM server to receive non-APNS notifications
    GCMService.sharedInstance().connectWithHandler({(error:NSError?) -> Void in
        if let error = error {
            print("Could not connect to GCM: \(error.localizedDescription)")
        } else {
            self.connectedToGCM = true
            print("Connected to GCM")
            // [START_EXCLUDE]
            self.subscribeToTopic()
            // [END_EXCLUDE]
        }
    })
}

func applicationWillTerminate(application: UIApplication) {

    NSUserDefaults.standardUserDefaults().setBool(false, forKey: "APP_RUNNING")

    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
    if let userInfo = notification.userInfo {
        NSNotificationCenter.defaultCenter().postNotificationName(
            "LoadEventViewController", object: nil, userInfo: userInfo)
    }
}




}

视图控制器,弹出本地通知
func scheduleLocal(message: String) {
    let settings = UIApplication.sharedApplication().currentUserNotificationSettings()

    if settings!.types == .None {
        let ac = UIAlertController(title: "Can't schedule", message: "Either we don't have permission to schedule notifications, or we haven't asked yet.", preferredStyle: .Alert)
        ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        presentViewController(ac, animated: true, completion: nil)
        return
    }

    // create a corresponding local notification
    let notification = UILocalNotification()
    notification.alertBody = message // text that will be displayed in the notification
    notification.alertAction = "open" // text that is displayed after "slide to..." on the lock screen - defaults to "slide to view"
    notification.fireDate = NSDate(timeIntervalSinceNow: 0) // todo item due date (when notification will be fired)
    notification.soundName = UILocalNotificationDefaultSoundName // play default sound
    notification.userInfo = ["UUID": 1, ] // assign a unique identifier to the notification so that we can retrieve it later
    notification.category = "TODO_CATEGORY"
    UIApplication.sharedApplication().scheduleLocalNotification(notification)
}

我有两个问题,
即使应用程序处于终止状态,是否可以接收和显示推送通知?如果是,如何?
我在代码中做错什么了吗?


最佳答案:

这是您的推送通知json?

aps: { "content-available" = 1; }

如果是,则发送无声推送。无提示推送意味着用户不会收到任何可视通知,只调用应用程序的应用程序委托回调。删除内容可用标记并传递消息文本。
如果应用程序在前台,iOS不会显示推送通知,只会调用代理。然后您可以显示警报视图或其他您喜欢的视图。
或者您可以显示:https://github.com/avielg/AGPushNote
关于“用户终止”状态,这里是Apple Doc(用于静默推送):
Apple documentation
使用此方法处理应用程序的传入远程通知。
与应用程序不同:DidReceivereMotification:方法,即
仅当应用程序在前台运行时调用
当应用程序在前台运行或
背景。此外,如果启用了远程通知
后台模式,系统启动应用程序(或从
挂起状态),当远程
通知到达。但是,系统不会自动
如果用户强制退出应用程序,则启动应用程序。在这种情况下,
用户必须重新启动应用程序或在系统启动之前重新启动设备。
尝试再次自动启动应用程序。