I am getting appData is deprecated below with the new Firebase project. What else should I use for data messages only?
- (void)messaging:(FIRMessaging *)messaging didReceiveMessage:(FIRMessagingRemoteMessage *)remoteMessage {
NSLog(#"Received data message: %#", remoteMessage.appData);
if(remoteMessage.appData[#"action"] != nil)
{
if([#"refresh" isEqual: remoteMessage.appData[#"action"]])
{
[[FIRInstanceID instanceID]deleteIDWithHandler:^(NSError * _Nullable error) {
NSLog(#"%#", error.description);
if(error == nil) {
}
}];
}
}
}
From https://firebase.google.com/support/release-notes/ios:
Deprecated FCM direct channel messaging via shouldEstablishDirectChannel. Instead, use APNs for downstream message delivery. Add content_available key to your payload if you want to continue use legacy APIs, but we strongly recommend HTTP v1 API as it provides full APNs support.
Related
I'm having two Firebase projects (on se same account, but could be two different accounts) and each project have an iOS app registered with the same bundle ID (so each .plist files have different sender IDs and project ID, but Bindle ID are the same).
When I configure Firebase messaging for each app separately using FirebaseApp.configure() and the firebase configuration .plist file for the app, it works, I can send FCM message and the app gets it.
(That means that both apps configurations on the Firebase console and Apple APNs keys, plist files are valid.)
But If I want to register both apps to enable multiple senders to send messages to my app, only the one registered as __FIRAPP_DEFAULT receives messages.
My configuration code is :
// this is configuration for the default "__FIRAPP_DEFAULT" using the base GoogleService-Info.plist file
FirebaseApp.configure()
// This is the second app configuration
let bundle = Bundle(for: type(of: self))
let path = bundle.path(forResource: "GoogleService-Info-second-app", ofType: "plist")
let options = FirebaseOptions.init(contentsOfFile: path!)
if options != nil {
FirebaseApp.configure(name: "app2", options: options!)
}
I can verify that both apps are well configured :
let apps = FirebaseApp.allApps
debugPrint(apps!)
Prints :
["app2": <FIRApp: 0x1704585a0>, "__FIRAPP_DEFAULT": <FIRApp: 0x17044a9b0>]
Then when I get the tokens from my AppDelegate using the following function:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let d = NSData(data: deviceToken)
print(d)
Messaging.messaging().retrieveFCMToken(forSenderID: firstAppSenderIdString) { (message, error) in
print("FCM token for app1: \(message!)")
}
Messaging.messaging().retrieveFCMToken(forSenderID: secondAppSenderIdString) { (message, error) in
print("FCM token for app2: \(message!)")
}
}
I get both valid tokens :
FCM token for app1: fwjJVG2-T9Q:APA91bG8xVN9S-F4aERzh0GtcLWAqOy3dBPed0vPUE4AS_Jt4rau1bmmhvGPjfQgwBt9krdI9e91GaA04x4PXm4eW9PsG52P-Vt8yeo2woWGl3CP6zE09cT8ouRmOoWBhFfZkLbzbGul
FCM token for app2: fwjJVG2-T9Q:APA91bGggGD0YBZO5tpDqwdYKEbGX4vTSXnhwFoc_lrHbLIIWg1WE4RjTS8NYZ--TX-GkoypuEM4Plb4h41mVcP0uYjvo2dGDO3SNyuo3GrsBRb4ISzoieC_bcJZs5MibLKrET97f49j
Also if I configure both apps on a custom app name and none on "__FIRAPP_DEFAULT" I don't get any messages even for the first one.
My guess is that only "__FIRAPP_DEFAULT" app can receive FCM messages. Could you confirm or tell me where I'm wrong ?
If only the default app can handle notifications, what's the use of being able to configure Firebase for more than one app in the same iOS application ?
If both firebase app are same bunder id and push certification, you can get FCM token work with push notification.
Because retrieveFCMToken don't work, I think you forget set APNSToken for FIRMessaging before call retrieveFCMToken
[FIRMessaging messaging].APNSToken = deviceToken;
[[FIRMessaging messaging] retrieveFCMTokenForSenderID:self.firstAppSenderIdString completion:^(NSString * _Nullable FCMToken, NSError * _Nullable error) {
NSLog(#"FCM token for app1: %# - error: %#", FCMToken, error);
}];
In addition, if the default app not config, FIRMessaging will be nil, let second app work you can using tokenWithAuthorizedEntity function.
[[FIRInstanceID instanceID] tokenWithAuthorizedEntity:self.secondAppSenderIdString scope:kFIRInstanceIDScopeFirebaseMessaging options:#{#"apns_token": deviceToken} handler:^(NSString * _Nullable token, NSError * _Nullable error) {
NSLog(#"FCM token for app2: %# - error: %#", token, error);
}];
I have this error in my phone device.
I already have enable keychain capabilities, but it doesnt work.
At the first launch application, the fcm sdk return the token, but after disconnect, and reconnect the Api return me nil in the token and this message error above is shown.
The token always return nil :
[[FIRInstanceID instanceID] token]
after the message error, next log error :
Failed to fetch default token Error Domain=com.firebase.iid Code=502 "(null)"
and next log error :
Failed to retrieve the default GCM token after 5 retries
It occurs when i disconnect and reconnect using fcm Api :
[[FIRMessaging messaging] disconnect];
and after foreground :
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
}
}];
I already enable keychain capabilities !
By default your "Keychain Capabilites" is turned to OFF, this is giving you the keychain error,
Simply go into your project navigator, then under the capabilites tab go scroll down to Keychain Sharing and switch it to ON. This should help you.
I need registrationId from Azure. Is it possible to get the registrationId from Azure?
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *) deviceToken {
SBNotificationHub* hub = [[SBNotificationHub alloc] initWithConnectionString:HUBLISTENACCESS
notificationHubPath:HUBNAME];
[hub registerNativeWithDeviceToken:deviceToken tags:nil completion:^(NSError* error) {
if (error != nil) {
NSLog(#"Error registering for notifications: %#", error);
}
else {
[self MessageBox:#"Registration Status" message:#"Registered"];
}
}];
}
Notifications are working fine but I need registrationId from Azure to send back to server.
I pored through the NotificationHub SDK code available at https://github.com/Azure/azure-notificationhubs/tree/master/iOS/WindowsAzureMessaging/WindowsAzureMessaging and found that the registration methods are all internal to the SDK class SBNotificationHub and are not exposed via the ObjC header file. Until they do that you either override the SDK header file with your own or accept that you can't access the registrationId from the SDK. The methods in question are retrieveAllRegistrationsWithDeviceToken or extractRegistrationIdFromLocationUri. The latter also requires that you call composeCreateRegistrationIdUri and then registrationOperationWithRequestUri.
Using the method
[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]
Im not quite sure what the parameters are calling for? What is the authorized entity and action? Also do I pass in the APNS token from apple to that method?
AUTHORIZED_ENTITY - Basically it asks for the google project id. It is numeric, and if you already had GCM integrated in your project before, it would be GCM_SENDER_ID (something like "568520103762"). Check your Google-info.plist to find it.
SCOPE - kFIRInstanceIDScopeFirebaseMessaging
OPTIONS - #{#"apns_token": deviceToken} (You will get DeviceToken in didRegisterForRemoteNotifications method)
HANDLER - Catch token if you have received token or catch the error here. If token comes nil, then wait for token in "tokenRefreshNotification" method, which will be called automatically if the token is nil in [FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]
Example:
if (![[FIRInstanceID instanceID] token]) {
[[FIRInstanceID instanceID] tokenWithAuthorizedEntity:_gcmSenderId scope:kFIRInstanceIDScopeFirebaseMessaging options:_registrationOptions handler:^(NSString * _Nullable token, NSError * _Nullable error) {
// Fetch the token or error
}];
}
You can do like this.
[[FIRInstanceID instanceID] setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeProd];
[[FIRInstanceID instanceID] tokenWithAuthorizedEntity:gcmSenderID scope:kFIRInstanceIDTokenRefreshNotification options:nil handler:^(NSString * _Nullable token, NSError * _Nullable error) {
NSLog(#"GCM Registration token = %#",token);
NSLog(#"GCM Registration error = %#",error);
}];
Version for Swift (based on #HeadOnn's answer):
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
Messaging.messaging().setAPNSToken(deviceToken, type: .prod) // may be excess
guard let plistPath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
let options = FirebaseOptions(contentsOfFile: plistPath)
else { return }
InstanceID.instanceID().token(withAuthorizedEntity: options.gcmSenderID,
scope: InstanceIDScopeFirebaseMessaging,
options: ["apns_token": deviceToken])
{ (token, error) in
// handle token and error
}
}
I am trying to push notifications through topic system in a iOS device with the new API of Google Cloud Messaging designed for iOS device.
I have the right certificates so I can receive notifications from a topic created. My code to subscribe to a topic is the following :
if (_registrationToken && _connectedToGCM) {
[[GCMPubSub sharedInstance] subscribeWithToken:_registrationToken
topic:topicToSubscribe
options:nil
handler:^(NSError *error) {
if (error) {
//handle error here
} else {
self.subscribedToTopic = true;
}
}];
}
I know the equivalent function to unsubscribe but this function need a topic name.
Is there a way to retrieve all topics where my app is possibly subscribed to unregistered them before subscribing ?
There is no way to retrieve the list of topics that your app is subscribed to from the Google Cloud Messaging service.
You have to keep track of the list and persist it on your app (hard coded, stored in preferences, database, file, etc.) or your server.
When you decide to let the user unsubscribe, retrieve the list of topics from where you stored it and pass it to unsubscribeWithToken:token:topic:options:handler as mentioned on the Implementing Topic Messaging page
Alternatively, when receiving messages you can check who is the message 'from'. If it is from a topic you are no longer interested in, you can unsubscribe instead of processing the message.
If you have the registration token it's possible to get the topics the device is subscribed to by using https://iid.googleapis.com/iid/info/IID_TOKEN (with authorization key in the header). Where IID_TOKEN is the registration token.
Find more info at https://developers.google.com/instance-id/reference/server#get_information_about_app_instances.
If you want unsubscribe from all topics simply execute:
GGLInstanceID *iid = [GGLInstanceID sharedInstance];
GGLInstanceIDDeleteHandler deleteHandler = ^void(NSError *error) {
if (error) {
// failed to delete the identity for the app
// do an exponential backoff and retry again.
} else {
// try to get a new ID
dispatch_async(dispatch_get_main_queue(), ^{
GGLInstanceIDHandler handler =
^void(NSString *identity, NSError *error) {
if (error) {
// failed to get the identity for the app
// handle error
} else {
NSString *instanceID = identity;
// handle InstanceID for the app
}
}
[iid getIDWithHandler:handler];
});
}
}
[iid deleteIDWithHandler:deleteHandler];
More info
Don't forget to refresh your TOKEN!