2016-02-11 15 views
1

首先,我是iOS開發新手,並且是新的swift。 我正在嘗試獲取適用於iOS的Google雲消息傳遞示例。iOS GCM - 連接到GCM部分不會執行

我已經安裝從https://developers.google.com/cloud-messaging/ios/start?ver=swift

的iOS(SWIFT版本)的谷歌雲通訊的例子,我做了與行動吧: pod try Google

我確實收到一個註冊令牌,但與處理器部分的連接在applicationDidBecomeActive部分似乎沒有出現錯誤,但似乎沒有進入連接到GCM部分。 來自:

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

我沒有看GCM for iOS, gcm connection handler is never called但唯一缺少的部分已經有包括來自pod try代碼示例英寸

以下是完整的AppDelegate.swift:

// 
// Copyright (c) 2015 Google Inc. 
// 
// Licensed under the Apache License, Version 2.0 (the "License"); 
// you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at 
// 
// http://www.apache.org/licenses/LICENSE-2.0 
// 
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
// See the License for the specific language governing permissions and 
// limitations under the License. 
// 

import UIKit 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate, GGLInstanceIDDelegate, GCMReceiverDelegate { 

    var window: UIWindow? 

    var connectedToGCM = false 
    var subscribedToTopic = false 
    var gcmSenderID: String? 
    var registrationToken: String? 
    var registrationOptions = [String: AnyObject]() 

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

    // [START register_for_remote_notifications] 
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: 
     [NSObject: AnyObject]?) -> Bool { 
    // [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.logLevel = GCMLogLevel.Debug 
    gcmConfig.receiverDelegate = self 
    GCMService.sharedInstance().startWithConfig(gcmConfig) 
    // [END start_gcm_service] 
    return true 
    } 

    func subscribeToTopic() { 
    // If the app has a registration token and is connected to GCM, proceed to subscribe to the 
    // topic 
    if(registrationToken != nil && connectedToGCM) { 
     GCMPubSub.sharedInstance().subscribeWithToken(self.registrationToken, topic: subscriptionTopic, 
     options: nil, handler: {(NSError error) -> Void in 
      if (error != nil) { 
      // 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; 
      print("Subscribed to \(self.subscriptionTopic)"); 
      NSLog("Subscribed to \(self.subscriptionTopic)"); 
      } 
     }) 
    } 
    } 

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

    // [START disconnect_gcm_service] 
    func applicationDidEnterBackground(application: UIApplication) { 
    GCMService.sharedInstance().disconnect() 
    // [START_EXCLUDE] 
    self.connectedToGCM = false 
    // [END_EXCLUDE] 
    } 
    // [END disconnect_gcm_service] 

    // [START receive_apns_token] 
    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 
     instanceIDConfig.logLevel = GGLInstanceIDLogLevel.Debug 
     // 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(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)") 
     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. 
    } 

} 

下面是從日誌信息:

2016-02-11 14:54:02.836 GcmExampleSwift[8484:] <GMR/INFO> App measurement v.1302000 started 
2016-02-11 14:54:02.844 GcmExampleSwift[8484:] <GMR/INFO> To enable debug logging set the following application argument: -GMRDebugEnabled (see http://goo.gl/Y0Yjwu) 
2016-02-11 14:54:02.845 GcmExampleSwift[8484:] <GMR/DEBUG> Debug logging enabled 
2016-02-11 14:54:02.845 GcmExampleSwift[8484:] <GMR/DEBUG> App measurement is monitoring the network status 
2016-02-11 14:54:02.871: GCM | Invalid key in checkin plist: GMSInstanceIDDeviceDataVersion 
2016-02-11 14:54:02.900: GCM | Signing into MCS 
2016-02-11 14:54:02.940 GcmExampleSwift[8484:] <GMR/DEBUG> App measurement is ready to receive events 
2016-02-11 14:54:02.962: GGLInstanceID | Save InstanceID library version 1.1.6 
2016-02-11 14:54:03.002 GcmExampleSwift[8484:] <GMR/DEBUG> No network. Upload task will not be scheduled 
2016-02-11 14:54:03.004 GcmExampleSwift[8484:] <GMR/DEBUG> Scheduling user engagement timer 
Registration Token: XXXXXXXXXXXXX 
2016-02-11 14:54:03.010 GcmExampleSwift[8484:] <GMR/DEBUG> Timer scheduled to fire in approx. (s): 3600 
2016-02-11 14:54:03.027 GcmExampleSwift[8484:] <GMR/INFO> App measurement enabled 
2016-02-11 14:54:03.028 GcmExampleSwift[8484:] <GMR/DEBUG> Network status has changed. code, status: 2, Connected 
2016-02-11 14:54:03.038 GcmExampleSwift[8484:] <GMR/DEBUG> Timer scheduled to fire in approx. (s): 2816.722655892372 
2016-02-11 14:54:03.039 GcmExampleSwift[8484:] <GMR/DEBUG> Upload task scheduled to be executed in approx. (s): 2816.722655892372 
2016-02-11 14:54:08.222: GCM | Successfully deleted 0 sync messages from store 
2016-02-11 14:54:44.905: GCM | Signing into MCS 
2016-02-11 14:55:28.909: GCM | Signing into MCS 
2016-02-11 14:56:16.914: GCM | Signing into MCS 
2016-02-11 14:57:12.918: GCM | Signing into MCS 
2016-02-11 14:58:24.923: GCM | Signing into MCS 
2016-02-11 15:00:08.927: GCM | Signing into MCS 
2016-02-11 15:02:46.495 GcmExampleSwift[8484:] <GMR/DEBUG> Scheduling user engagement timer 
2016-02-11 15:02:46.532 GcmExampleSwift[8484:] <GMR/DEBUG> Canceling active timer 
2016-02-11 15:02:46.534 GcmExampleSwift[8484:] <GMR/DEBUG> Timer scheduled to fire in approx. (s): 3600 
2016-02-11 15:02:46.535 GcmExampleSwift[8484:] <GMR/DEBUG> Canceling active timer 
2016-02-11 15:02:46.536 GcmExampleSwift[8484:] <GMR/DEBUG> Logging event: origin, name, params: auto, _e, { 
     "_et" = 523435; 
     "_o" = auto; 
    } 
2016-02-11 15:02:46.551 GcmExampleSwift[8484:] <GMR/DEBUG> Event logged. Event name, event params: _e, { 
     "_et" = 523435; 
     "_o" = auto; 
    } 
2016-02-11 15:02:46.566 GcmExampleSwift[8484:] <GMR/DEBUG> Do not schedule an upload task. Task already exists 
2016-02-11 15:02:56.662: GCM | Signing into MCS 
2016-02-11 15:02:56.681 GcmExampleSwift[8484:] <GMR/DEBUG> Scheduling user engagement timer 
2016-02-11 15:02:56.683 GcmExampleSwift[8484:] <GMR/DEBUG> Timer scheduled to fire in approx. (s): 3600 
2016-02-11 15:03:38.666: GCM | Signing into MCS 
2016-02-11 15:04:22.671: GCM | Signing into MCS 
2016-02-11 15:05:10.675: GCM | Signing into MCS 
2016-02-11 15:06:06.680: GCM | Signing into MCS 
2016-02-11 15:07:18.664: GCM | Signing into MCS 
2016-02-11 15:08:43.991: GCM | Signing into MCS 
2016-02-11 15:11:31.996: GCM | Signing into MCS 
2016-02-11 15:16:27.991: GCM | Signing into MCS 
2016-02-11 15:25:39.985: GCM | Signing into MCS 

我取代了真正的regsitration令牌XXXXXXXXXXXXX

從日誌中還注意到:

GCM | Invalid key in checkin plist: GMSInstanceIDDeviceDataVersion

這是正常的嗎?我無法找到關於這意味着什麼的信息?

通過GCM向設備發送消息確實有效,如果您修改上面的示例代碼而不是connectedToGCM的檢查,您還可以接收主題消息。 但是,在示例代碼中肯定不會出現錯誤,我認爲我的配置有問題,但我無法弄清楚。任何幫助,將不勝感激。

+0

您需要從開發者控制檯爲GCM生成API密鑰 –

+0

您是否參考https://developers.google.com/cloud-messaging/ios上的「獲取配置文件」部分的GoogleService-Info.plist /啓動?版本=快捷? 如果是這樣,我確實這樣做了,它包含在應用程序中,當plist不可用時會得到不同的錯誤。 – paradox

回答

0

消息:GCM | Invalid key in checkin plist: GMSInstanceIDDeviceDataVersion與連接處理程序沒有連接無關。 這是一個已知問題:有關更多信息,請參見https://github.com/googlesamples/google-services/issues/171

連接處理程序代碼不按預期方式工作似乎與防火牆有關。看起來並不是所有需要打開的端口。

注意:仍然可以獲取消息,但連接處理程序代碼只是無法正常工作。

https://developers.google.com/cloud-messaging/http#message-with-payload--data-message如果您位於受限制的網絡上,請參閱所需的防火牆更改。

0

請檢查此documentation以瞭解可能的錯誤原因。也許在請求中傳遞的註冊令牌有問題;它可能是一個不可恢復的錯誤,也將需要從服務器數據庫中刪除註冊。

這個SO question也可能有幫助。

+0

我使用註冊令牌將消息發送到設備時沒有問題。就像我說的我甚至可以修改Swift代碼來註冊主題,然後我甚至可以通過主題接收消息。問題是示例代碼永遠不會註冊到某個主題,因爲它不會將「connectedToGCM」設置爲true,因爲連接處理程序不會觸發。此外,我不確定「檢入plist中的無效鍵:GMSInstanceIDDeviceDataVersion」是否正常。 – paradox

+0

我也看到http://stackoverflow.com/questions/33296515/gcm-ios-notregistered-issue和我已經改變了配置文件,但行爲保持不變,如上所述。 – paradox