在GCM client guide for iOS中,它讨论了实施onTokenRefresh
方法,但它没有说明要在哪个类上实现,或者Google代码如何知道发送此消息的对象至。我看到GGLInstanceIDDelegate
protocol中指定了onTokenRefresh
方法,GGLInstanceIDConfig
class中有一个名为id<GGLInstanceIDDelegate>
的{{1}}类型的属性,但这一点无处可去示例代码中设置的属性,指南也没有谈到设置它。示例代码使用delegate
的唯一位置是将默认配置直接传递给GGLInstanceIDConfig
GGLInstanceID
而不设置任何内容:
startWithConfig:
我们需要单独设置吗?
同样,关于发送上游消息的指南部分讨论了实现[[GGLInstanceID sharedInstance] startWithConfig:[GGLInstanceIDConfig defaultConfig]];
和willSendDataMessageWithID
方法,但它没有说明实现这些方法的类或GCM如何知道什么对象发送给他们。它们位于GCMReceiverDelegate
protocol中,GCMConfig
class中有一个名为didSendDataMessageWithID
的{{1}}类型的属性,但同样,该属性未在示例代码中设置指南不讨论设置它。
我们需要单独设置吗?
答案 0 :(得分:1)
我有点晚了,但是我想说通过浏览Google文档并了解它在GIT上的示例项目中的工作原理,所有这些内容都更容易理清: https://github.com/googlesamples/google-services/blob/master/ios/gcm/GcmExampleSwift/AppDelegate.swift
恰巧,Google在AppDelegate中实现了大部分功能。
//
// 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.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: {(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)");
}
})
}
}
// [START connect_gcm_service]
func applicationDidBecomeActive( application: UIApplication) {
// 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]
}
})
}
// [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
// 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.
}
}
答案 1 :(得分:0)
是的,您必须设置自定义代理才能接收回调。这就是我为GCMReceiverDelegate
最初配置GCM
,
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
self.apnsToken = deviceToken;
WEAKIFY(self);
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
STRONGIFY(self);
self.notificationCenter = [[GCMNotificationCenter alloc] init]
// InstanceID
GGLInstanceIDConfig *instanceIDConfig = [GGLInstanceIDConfig defaultConfig];
instanceIDConfig.logLevel = kGGLInstanceIDLevelDebug;
instanceIDConfig.delegate = self.notificationCenter;
[[GGLInstanceID sharedInstance] startWithConfig:instanceIDConfig];
// GCM
GCMConfig *config = [GCMConfig defaultConfig];
config.logLevel = kGCMLogLevelDebug;
config.receiverDelegate = [[GCMReceiver alloc] init];
[[GCMService sharedInstance] startWithConfig:config];
}
}
}
GCMReceiver.m
将会有。
#pragma mark - GCM delegate
- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error {
if (error) {
// Failed to send the message.
} else {
// Will send message
}
}
- (void)didSendDataMessageWithID:(NSString *)messageID {
// Did send message successfully
}
- (void)didDeleteMessagesOnServer {
// Some messages were deleted on the server. Let the server
// know about this to retrieve them.
}
#pragma mark - InstanceID delegate
- (void)onTokenRefresh {
// Fetch all the tokens for all auth-entities and send them
// to the server.
}
请注意,在第一个回调willSendDataMessageWithID:error:
中,如果没有error
对象,那么您将无法获得回调,这个对象不是很好,将在下一版本中由Google更正。
您也必须对GGLInstanceIDDelegate
执行相同的操作。