I have configured GCM in my existing app and i am receiving the notifications there. Now i am facing two problem:
1) I am not receiving notifications When i exit the application or application is in the background.
2) I am not receiving notification in iphone's notification area, only when my app is running i only direct receive alert message there. And when i pull down notification area i get this message in xcode's console "Could not connect to GCM: The operation couldn’t be completed. (com.google.gcm error 2001.)"
My PHP file is below
<?php
// Payload data you want to send to iOSdevice(s)
// (it will be accessible via intent extras)
$data = array( 'message' => 'Hello World!');
// The recipient registration tokens for this notification
// http://developer.android.com/google/gcm/
$ids = array( 'kucy6xoUmx********eeRsla' );
// Send a GCM push
sendGoogleCloudMessage( $data, $ids );
function sendGoogleCloudMessage( $data, $ids )
{
// Insert real GCM API key from Google APIs Console
// https://code.google.com/apis/console/
$apiKey = 'AIz******9JA';
// Define URL to GCM endpoint
$url = 'https://gcm-http.googleapis.com/gcm/send';
// Set GCM post variables (device IDs and push payload)
$post = array(
'registration_ids' => $ids,
'data' => $data,
);
// Set CURL request headers (authentication and type)
$headers = array(
'Authorization: key=' . $apiKey,
'Content-Type: application/json'
);
// Initialize curl handle
$ch = curl_init();
// Set URL to GCM endpoint
curl_setopt( $ch, CURLOPT_URL, $url );
// Set request method to POST
curl_setopt( $ch, CURLOPT_POST, true );
// Set our custom headers
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
// Get the response back as string instead of printing it
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// Set JSON post data
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post ) );
// Actually send the push
$result = curl_exec( $ch );
// Error handling
if ( curl_errno( $ch ) )
{
echo 'GCM error: ' . curl_error( $ch );
}
// Close curl handle
curl_close( $ch );
// Debug GCM response
echo $result;
}
?>
Here is my AppDelegate.m file
// [START register_for_remote_notifications]
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// [START_EXCLUDE]
_registrationKey = #"onRegistrationCompleted";
_messageKey = #"onMessageReceived";
// Configure the Google context: parses the GoogleService-Info.plist, and initializes
// the services that have entries in the file
NSError* configureError;
[[GGLContext sharedInstance] configureWithError:&configureError];
NSAssert(!configureError, #"Error configuring Google services: %#", configureError);
_gcmSenderID = [[[GGLContext sharedInstance] configuration] gcmSenderID];
// Register for remote notifications
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
// iOS 7.1 or earlier
UIRemoteNotificationType allNotificationTypes =
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
[application registerForRemoteNotificationTypes:allNotificationTypes];
} else {
// iOS 8 or later
// [END_EXCLUDE]
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
// [END register_for_remote_notifications]
// [START start_gcm_service]
GCMConfig *gcmConfig = [GCMConfig defaultConfig];
gcmConfig.receiverDelegate = self;
[[GCMService sharedInstance] startWithConfig:gcmConfig];
// [END start_gcm_service]
__weak typeof(self) weakSelf = self;
// Handler for registration token request
_registrationHandler = ^(NSString *registrationToken, NSError *error){
if (registrationToken != nil) {
weakSelf.registrationToken = registrationToken;
NSLog(#"Registration Token: %#", registrationToken);
[weakSelf subscribeToTopic];
NSDictionary *userInfo = #{#"registrationToken":registrationToken};
[[NSNotificationCenter defaultCenter] postNotificationName:weakSelf.registrationKey
object:nil
userInfo:userInfo];
} else {
NSLog(#"Registration to GCM failed with error: %#", error.localizedDescription);
NSDictionary *userInfo = #{#"error":error.localizedDescription};
[[NSNotificationCenter defaultCenter] postNotificationName:weakSelf.registrationKey
object:nil
userInfo:userInfo];
}
};
return YES;
}
- (void)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:_registrationToken
topic:SubscriptionTopic
options:nil
handler:^(NSError *error) {
if (error) {
// Treat the "already subscribed" error more gently
if (error.code == 3001) {
NSLog(#"Already subscribed to %#",
SubscriptionTopic);
} else {
NSLog(#"Subscription failed: %#",
error.localizedDescription);
}
} else {
self.subscribedToTopic = true;
NSLog(#"Subscribed to %#", SubscriptionTopic);
}
}];
}
}
// [START connect_gcm_service]
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Connect to the GCM server to receive non-APNS notifications
[[GCMService sharedInstance] connectWithHandler:^(NSError *error) {
if (error) {
NSLog(#"Could not connect to GCM: %#", error.localizedDescription);
} else {
_connectedToGCM = true;
NSLog(#"Connected to GCM");
// [START_EXCLUDE]
[self subscribeToTopic];
// [END_EXCLUDE]
}
}];
}
// [END connect_gcm_service]
// [START disconnect_gcm_service]
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[GCMService sharedInstance] disconnect];
// [START_EXCLUDE]
_connectedToGCM = NO;
// [END_EXCLUDE]
}
// [END disconnect_gcm_service]
// [START receive_apns_token]
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// [END receive_apns_token]
// [START get_gcm_reg_token]
// Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
GGLInstanceIDConfig *instanceIDConfig = [GGLInstanceIDConfig defaultConfig];
instanceIDConfig.delegate = self;
// Start the GGLInstanceID shared instance with the that config and request a registration
// token to enable reception of notifications
[[GGLInstanceID sharedInstance] startWithConfig:instanceIDConfig];
_registrationOptions = #{kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:#"NO"};
[[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:_gcmSenderID
scope:kGGLInstanceIDScopeGCM
options:_registrationOptions
handler:_registrationHandler];
// [END get_gcm_reg_token]
}
// [START receive_apns_token_error]
- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Registration for remote notification failed with error: %#", error.localizedDescription);
// [END receive_apns_token_error]
NSDictionary *userInfo = #{#"error" :error.localizedDescription};
[[NSNotificationCenter defaultCenter] postNotificationName:_registrationKey
object:nil
userInfo:userInfo];
}
// [START ack_message_reception]
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"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]
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
NSLog(#"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(UIBackgroundFetchResultNoData);
// [END_EXCLUDE]
}
// [END ack_message_reception]
// [START on_token_refresh]
- (void)onTokenRefresh {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
NSLog(#"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]
- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error {
if (error) {
// Failed to send the message.
} else {
// Will send message, you can save the messageID to track the message
}
}
- (void)didSendDataMessageWithID:(NSString *)messageID {
// Did successfully send message identified by messageID
}
// [END upstream_callbacks]
- (void)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.
}
I am not a php script master so please help me that how i can resolve my issues.
I have added
'content_available' => true,//to trigger when iOS app is in background
'priority' => 'high',
'notification' => $data,
$data = array( 'message' => 'Hello World!', 'body' => 'Hello World!');
to your code.
Please try below code;
<?php
// Payload data you want to send to iOSdevice(s)
// (it will be accessible via intent extras)
$data = array( 'message' => 'Hello World!', 'body' => 'Hello World!');
// The recipient registration tokens for this notification
// http://developer.android.com/google/gcm/
$ids = array( 'kucy6xoUmx********eeRsla' );
// Send a GCM push
sendGoogleCloudMessage( $data, $ids );
function sendGoogleCloudMessage( $data, $ids )
{
// Insert real GCM API key from Google APIs Console
// https://code.google.com/apis/console/
$apiKey = 'AIz******9JA';
// Define URL to GCM endpoint
$url = 'https://gcm-http.googleapis.com/gcm/send';
// Set GCM post variables (device IDs and push payload)
$post = array(
'registration_ids' => $ids,
'data' => $data,
'content_available' => true,
'priority' => 'high',
'notification' => $data,
);
// Set CURL request headers (authentication and type)
$headers = array(
'Authorization: key=' . $apiKey,
'Content-Type: application/json'
);
// Initialize curl handle
$ch = curl_init();
// Set URL to GCM endpoint
curl_setopt( $ch, CURLOPT_URL, $url );
// Set request method to POST
curl_setopt( $ch, CURLOPT_POST, true );
// Set our custom headers
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
// Get the response back as string instead of printing it
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// Set JSON post data
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post ) );
// Actually send the push
$result = curl_exec( $ch );
// Error handling
if ( curl_errno( $ch ) )
{
echo 'GCM error: ' . curl_error( $ch );
}
// Close curl handle
curl_close( $ch );
// Debug GCM response
echo $result;
}
?>
on IOS side;
Follow orders on GCM Site
EDIT 1:
You may try sending notification for ios;
I edited your php code above;
Changes are;
'notification' => $data,
and
$data = array( 'message' => 'Hello World!', 'body' => 'Hello World!');
GCM receiving notification in invalid state 2.
Developers who are using GCM integration for both Android and iOS need to add specific things in their Post call to the GCM Server.
For iOS:
We need two additional things to make the same call work in iOS:
'notification' => $data,
'content_available'=> 'true',
The Apple push notifications service requires content_available is true. And then 'notification'=> $data helps the Notification center to know that the notification has arrived and needs to be pushed to the device.
Related
I am getting the following error when trying to send a Push Notification using Google Firebase:
{"multicast_id":1559489545169770337,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"MismatchSenderId"}]}
Can anyone give any clues why please?
It is a new setup and not being imported from GMC.
manifest.json contains:
"gcm_sender_id": "1225****"
This matches "Project Settings" > "Cloud Messaging" > [Sender ID]
The code for registering the user is:
function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4);
var base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
var rawData = window.atob(base64);
var outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function subscribePush() {
navigator.serviceWorker.ready.then(function(registration) {
if (!registration.pushManager) {
alert('Your browser doesn\'t support push notification.');
return false;
}
registration.pushManager.subscribe({
userVisibleOnly: true //Set user to see every notification
, applicationServerKey: urlBase64ToUint8Array('*******')
//The "PUBLIC KEY PAIR" under Web configuration. Have tried with and without urlBase64ToUint8Array()
})
.then(function (subscription) {
console.info('Push notification subscribed.');
console.log(subscription);
//saveSubscriptionID(subscription);
})
.catch(function (error) {
console.error('Push notification subscription error: ', error);
});
})
}
My code is registering the user and the response from Firebase is (including "REGISTRATION ID"):
Data {"endpoint":"https://fcm.googleapis.com/fcm/send/****:*****","expirationTime":null,"keys":{"p256dh":"****","auth":"****"}}
I am then using this PHP cURL:
$id = "****:*****"; // "REGISTRATION ID" from the response above. If this is wrong it throws an error ("InvalidRegistration"), so I know that this is correct.
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array (
'registration_ids' => array (
$id
),
'data' => array (
"message" => "Test"
)
);
$fields = json_encode ( $fields );
$headers = array (
'Authorization: key=' . "********", //This is the "Server key" above "Sender ID"
//This matches "Project Settings" > "Cloud Messaging" > [Server Key]
//If this is wrong it returns: INVALID_KEY error 401. So I know this is correct.
'Content-Type: application/json'
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, true );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $fields );
$result = curl_exec ( $ch );
echo $result;
curl_close ( $ch );
So I eventually figured this out. Instead of using the Subscription ID from the end of
https://fcm.googleapis.com/fcm/send/ABCDEF:KJHASKHDASDetc
I used the following code, and used the TOKEN instead and used that as the "registration_ids" in the CURL post
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-messaging.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: "****",
authDomain: "****",
projectId: "****",
storageBucket: "****",
messagingSenderId: "****",
appId: "****",
measurementId: "****"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
const messaging = firebase.messaging();
messaging.requestPermission()
.then(function() {
console.log('Notification permission granted.');
return messaging.getToken()
})
.then(function(result) {
console.log("The token is: ", result);
})
.catch(function(err) {
console.log('Unable to get permission to notify.', err);
});
messaging.getToken({ vapidKey: '*****-*****' }).then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
// ...
console.log("currentToken: ", currentToken);
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
I'm trying to write an application to receive notifications via Firebase Cloud Messaging. It initially worked when I tried to send the message via the Firebase console, but then the moment I tried doing the same using PHP webservice, in response, it showed success, but I neither received the message nor am I able to get any more notifications via Firebase console. How can I fix this?
My code in the server side:
<?php
function send_notification ($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => $tokens,
'data' => $message
);
$headers = array(
'Authorization:key = AIzaSyDjrLKZGs4OcIgBPxpFnTzGeZHur4v9V8U',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
$conn = mysqli_connect("localhost:3306", "minaaaa", "tt#2018", "dbSurvey");
$sql = "Select Token From users";
$result = mysqli_query($conn,$sql);
$tokens = array();
if(mysqli_num_rows($result) > 0 ){
while ($row = mysqli_fetch_assoc($result)) {
$tokens[] = $row["Token"];
}
}
mysqli_close($conn);
$message = array("message" => " FCM PUSH NOTIFICATION TEST MESSAGE");
$message_status = send_notification($tokens, $message);
echo $message_status;
?>
Code in Swift:
UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
Util.copyFile(fileName: "db.zanjanwireFinal01.db")
//let alert = UIAlertController(title: title, message: message , preferredStyle: .alert)
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge]){(isGranted, err)
in
if err != nil {
}
else
{
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
if let token = InstanceID.instanceID().token() {
print("DCS: " + token)
self.RegisterUsers(testStr: token)
}
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
FirebaseApp.configure()
return true
}
func ConnectToFCM() {
Messaging.messaging().shouldEstablishDirectChannel = true
if let token = InstanceID.instanceID().token() {
print("DCS: " + token)
RegisterUsers(testStr: token)
}
}
func RegisterUsers(testStr:String){
let request = NSMutableURLRequest(url: NSURL(string:
request.httpMethod = "POST"
var dataString = "Token=\(testStr)"
print (dataString)
request.httpBody = dataString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil {
print("fffffffffatemeeeeeee")
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
}
task.resume()
}
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.
//FirstMenueViewController().update()
Messaging.messaging().shouldEstablishDirectChannel = false
}
func applicationWillEnterForeground(_ application: UIApplication) {
FirstMenueViewController().update()
// 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.
ConnectToFCM()
}
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:.
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
ConnectToFCM()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
UIApplication.shared.applicationIconBadgeNumber += 1
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "com.DouglasDevlops.BadgeWasUpdated"), object: nil)
}
Structure your notification payload like this,
Extremely grateful for any help with this.. all I want to do is use my php code to send notifications to all users subscribed to topic "global". Does anyone know why it might not work? Since I want everyone using the app to get the notifications, I will subscribe everyone (unless there is a better way). Here is my php to try to send the notification to my topic global:
<?php
define( 'API_ACCESS_KEY', 'hidden...hidden' );
$msg = array
(
'message' => 'here is a message. message',
'title' => 'This is a title. title',
'vibrate' => 1,
'sound' => 1
);
$fields = array
(
'to' => "/topics/global",
'data' => $msg,
'priority' => 'high'
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec( $ch );
curl_close( $ch );
echo $result;
?>
I am lacking knowledge but from the $result echo it didn't look like any failure message. This is what I got:
{"message_id":7591682951632927615}
In my Firebase console, I cannot even see the topic "global" so I can't test that sending to the topic works on my device. From what I read online, it could take awhile for a subscribed topic to appear in the console. Just to clarify, sending notifications to all devices using user segment set to the App works in the console!
Is there anything that I can do to verify that my app is actually subscribing users to the topic "global"? Maybe this is the problem. Here is the relevant swift code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// For iOS 10 data message (sent via FCM)
FIRMessaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
return true
}
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print("applicationReceivedRemoteMessage")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
FIRMessaging.messaging().subscribe(toTopic: "/topics/global")
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
/*
// Print message ID.
if let messageID = userInfo["gcmMessageIDKey"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
*/
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
if application.applicationState == UIApplicationState.active {
print("GOT IN HERE")
var pushNotificationMessage = ""
if let aps = userInfo["aps"] as? NSDictionary {
if let alert = aps["alert"] as? NSDictionary {
if let message = alert["message"] as? NSString {
pushNotificationMessage = message as String
}
} else if let alert = aps["alert"] as? NSString {
pushNotificationMessage = alert as String
}
}
let notificationAlert = UIAlertController(title: nil, message: pushNotificationMessage, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: {
(alert: UIAlertAction!) -> Void in
})
defaultAction.setValue(Constants.activePushNotificationOKColor, forKey: "titleTextColor")
notificationAlert.addAction(defaultAction)
self.window?.rootViewController?.present(notificationAlert, animated: true, completion: nil)
}
}
To send a notification, store the parameters in notification, not data:
$fields = array
(
'to' => "/topics/global",
'notification' => $msg, // <= CHANGED
'priority' => 'high'
);
Also look at Table 2a in the documentation for Notification payload support. message is not supported, use body instead.
$msg = array
(
'body' => 'here is a message. message', // <= CHANGED
'title' => 'This is a title. title',
'vibrate' => 1,
'sound' => 1
);
I am using FIREBASE CLOUD MESSAGING service with my ionic product and phonegap-plugin-push cordova plugin to get push notification from PHP BACK END.
When I am trying to get push notification then php end is getting result with success as below.
Sample Push Data Payload
{"multicast_id":8853634389214913500,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1495614850271706%39688dd8f9fd7ecd"}]}
Technology specification :
cordova push notification plugin version :1.9.4
Platform and Version: Ionic V1
Ionic CLI version : 2.1.13
Cordova version : cordova --6.4.0
Android platform for cordova :6.0.0
Android) What device vendor I have tested : Samsung, HUWAWEI, Xiaomi
etc.
Sample Code that illustrates the problem as below
IONIC PART:
//Push Notification
if (window.cordova) {
if (!localStorage.getItem('device_token')) {
var apkId = 0;
var iosId = 0;
var options = {
android: {
senderID: MY FCM SENDER ID,
icon: "alert",
},
ios: {
alert: "true",
badge: "true",
sound: "true"
},
windows: {}
};
//localStorage.getItem('gcmRegId')
// initialize
$cordovaPushV5.initialize(options).then(function () {
// start listening for new notifications
$cordovaPushV5.onNotification();
// start listening for errors
$cordovaPushV5.onError();
// register to get registrationId
$cordovaPushV5.register().then(function (data) {
//alert("GCM"+data);
// if Android device.
if (ionic.Platform.isAndroid()) {
apkId = data;
}
// if ios device.
if (ionic.Platform.isIOS()) {
iosId = data;
}
// Updating member details with apkId or iosId
var pushParams = {
'app_token': Config.appToken,
'device_uiu_token': device.uuid,
'apk_token': apkId,
'ios_token': iosId
}
$http.post(Config.apiUrl + "member/save_token", pushParams)
.success(function (data) {
if (data.status == 200) {
localStorage.setItem("device_token", device.uuid);
}
/* else{
alert("Sorry!Error occurs!");
} */
});
})
// Updating end.
});
// triggered every time notification received
$rootScope.$on('$cordovaPushV5:notificationReceived', function (event, data) {
alert("recieved" + JSON.stringify(data));
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
});
// triggered every time error occurs
$rootScope.$on('$cordovaPushV5:errorOcurred', function (event, e) {
alert('push ERROR' + e.message);
// e.message
});
// push notification end
PHP PART:
$push_title = $this->input->post('push_title');
$push_msg = $this->input->post('push_msg');
$members = $this->members_model->get_members();
$apk_tokens = array();
$ios_tokens = array();
foreach ($members as $member) {
if ($member['apk_token'] != 0 || $member['apk_token'] != "") {
array_push($apk_tokens, $member['apk_token']);
}
if ($member['ios_token'] != 0 || $member['ios_token'] != "") {
array_push($ios_tokens, $member['ios_token']);
}
}
//Sending the push notification using GCM.
$msg = array(
'message' => $push_msg,
'title' => $push_title,
'vibrate' => 1,
'sound' => 1,
'largeIcon' => 'large_icon',
'smallIcon' => 'small_icon',
);
$fields = array
(
'registration_ids' => $apk_tokens,
'data' => $msg,
'priority' => 'high'
);
$headers = array
(
'Authorization: MY FCM SERVER KEY',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
curl_close($ch);
echo $result;
Thanks in advance!
If you want to show the notification on lock screen, use notification in $fields. The object requires title and body elements.
https://firebase.google.com/docs/cloud-messaging/server#implementing-http-connection-server-protocol
$fields = array
(
'registration_ids' => $apk_tokens,
'data' => $msg,
'priority' => 'high',
'notification' => array(
'title' => 'This is title',
'body' => 'This is body'
)
);
I did not try this code, but same issue with node.js SDK has been fixed in this way.
after google launch their new FCM SDK with iOS capability i was abel to receive the notification from the console well either the app was in background or in active state now i am trying to make my server send the push notification as mentioned here i follow up the documentation steps as mention in https://firebase.google.com/docs/cloud-messaging/server but the result is :
{"multicast_id":XXXXXXXXXXXXXXX,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
The PHP Script
<?php
define( 'API_ACCESS_KEY', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
$registrationIds = array('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
$msg = array
(
'message' => 'here is a message. message',
'title' => 'This is a title. title',
'subtitle' => 'This is a subtitle. subtitle',
'tickerText' => 'Ticker text here...Ticker text here...Ticker text here',
'vibrate' => 1,
'sound' => 1,
'largeIcon' => 'large_icon',
'smallIcon' => 'small_icon'
);
$fields = array
(
'registration_ids' => $registrationIds,
'data' => $msg
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json',
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
echo $result;
?>
this code was found on github https://gist.github.com/prime31/5675017 but i make some modification to fit my case
and after searching for related question on stack i just found the following Notification in iOS using new Firebase Messaging SDK, and Invalid Registration Id with my gcm php server but they could not help me in solving my problem.
here is the cliend side but as i mentioned before the app receive the notification from the console.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
if(ver >= 8 && ver<9)
{
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)])
{
[[UIApplication sharedApplication] registerForRemoteNotifications];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
}else if (ver >=9){
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else{
//iOS6 and iOS7 specific code
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeAlert];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
[FIRApp configure];
[self connectToFcm];
// Override point for customization after application launch.
return YES;
}
- (void)tokenRefreshNotification:(NSNotification *)notification {
// Note that this callback will be fired everytime a new token is generated, including the first
// time. So if you need to retrieve the token as soon as it is available this is where that
// should be done.
NSString *refreshedToken = [[FIRInstanceID instanceID] token];
NSLog(#"InstanceID token: %#", refreshedToken);
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSDictionary *newUserInfo = [userInfo objectForKey:#"notification"];
NSLog(#"the user info is : %#",newUserInfo);
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateBackground || state == UIApplicationStateInactive)
{
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.userInfo = newUserInfo;
localNotification.alertTitle = [newUserInfo objectForKey:#"title"];
localNotification.alertBody = [newUserInfo objectForKey:#"body"];
localNotification.applicationIconBadgeNumber = 0;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.fireDate = [NSDate date];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
else if (state == UIApplicationStateActive) {
AudioServicesPlaySystemSound(1054);
UIImage *icon = [UIImage imageNamed:#"placeholderimage"];
NSString *title = [newUserInfo objectForKey:#"title"];
NSString *body = [newUserInfo objectForKey:#"body"];
notification = [MPGNotification notificationWithTitle:title subtitle:body backgroundColor:[UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1.0f] iconImage:icon];
notification.duration = 5.0;
notification.swipeToDismissEnabled = NO;
[notification show];
}
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#"<>"]];
token = [token stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"content---%#", token);
}
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
}
}];
}