fechanique / cordova-plugin-fcm

Google FCM Push Notifications Cordova Plugin
624 stars 990 forks source link

FCMPlugin.onNotification() does not get called for incoming push notifications #154

Open bmwertman opened 7 years ago

bmwertman commented 7 years ago

The issue I'm seeing sounds kind of similar to what is described with issue #123. But I wasn't certain so I thought I would add my own details to be sure.

This was all working when I set it up about a month ago. I still receive push notifications when the app is closed or in the background.

But if the app is in the foreground I get no notification. Which is actually fine because I was handling that with FCMPlugin.onNotification callback when everything was working.

And FCMPlugin.onNotification callback, success or error in my $ionPlatform.ready() never run no matter the state of the app.

Subscribe factory - Used in Rooms factory

myApp.factory('pushSubscribe', [
  '$firebaseArray',
  function ($firebaseArray) {
  return $firebaseArray.$extend({
    $$added: function(room){
      // Room topic is the $id of the chat room
      FCMPlugin.subscribeToTopic(room.key,
        function(success){
          //Success is being ran here with "OK" response
          //when a new chat room is added
        },
        function(error){
          // Not seeing any errors here
        }
      );
    },
    $$removed: function(room){
      FCMPlugin.unsubscribeFromTopic(room.key);
    }
  });
}]);

Rooms factory - registers chatters for push notifications

myApp.factory('Rooms', [
  '$firebaseArray',
  '$firebaseObject',
  'userService',
  'pushSubscribe',
  function ($firebaseArray, $firebaseObject, userService, pushSubscribe) {
  var ref = firebase.database().ref(),
      user = userService.getUser();
      userRoomsRef = firebase.database().ref('user-rooms').child(user.$id),
      roomsRef = firebase.database().ref('/rooms'),
      userRoom = new pushSubscribe(userRoomsRef);// Subscribes the current user to push notifications for all of their user-rooms
  return {
  // CRUD methods for rooms here
  }
}]);

app.js .run() - Supposed to listen for incoming notifications and handle them according to the state of the app but it isn't.

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
     FCMPlugin.onNotification(
       function(data){ //callback
         if(data.wasTapped){
           //Notification was received on device tray and tapped by the user.
           console.log( JSON.stringify(data) );
         } else {
           //Notification was received in foreground. Maybe the user needs to be notified.
           console.log( JSON.stringify(data) );
         }
       },
       function(msg){ //success handler
         console.log('onNotification callback successfully registered: ' + msg);
       },
       function(err){ //error handler
         console.log('Error registering onNotification callback: ' + err);
       }
     );
   });

node-gcm push router - Hosted on Heroku all chats hit routers url

var router = require('express').Router();
var firebase = require('firebase');
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
var gcm = require('node-gcm');
var sender = new gcm.Sender('MY_AUTH_TOKEN');

router.get('/', function(req, res){
  res.status(200).json({ message: 'GET route on router'});
});

router.post('/', jsonParser, function(req, res){
  firebase.auth().verifyIdToken(req.body.token)
  .then(function(user){
    var message = new gcm.Message({
      priority: 'high', 
      notification: {
        click_action: "FCM_PLUGIN_ACTIVITY",
        title: req.body.sender_name,
        body: req.body.message
      },
      data: {
        state: req.body.state,
        roomId: req.body.roomId,
        sender_imgUrl: req.body.sender_imgURL
      }
    });
    sender.send(message, { topic: req.body.topic }, function(err, response){
      if(err){
        res.status(500).json({ error: err });
      } else {
        res.status(200).json({ response: 'Push notification sent' });
      }
    });
  })
  .catch(function(err){
    res.status(500).json({ response: err });
  });
});

module.exports = router;

The send message method

$scope.sendMessage = function() {
        // Get the users auth jwt to verify them on the node router
        firebase.auth().currentUser.getToken(true)
        .then(function(userToken){
            $http({
                method: 'POST',
                url:'MY_HEROKU_HOSTED_NODE_ROUTER_URL',
                data:{ 
                    token: userToken,
                    message: $scope.IM.textMessage,
                    sender_name: $scope.user.name,
                    topic: '/topics/' + $state.params.roomId,
                    state: 'app.room',
                    roomId: $state.params.roomId,
                    sender_imgURL: $scope.user.pic,
                    chatters: chatters 
                }
            })
            .then(function(res){
                //Chats factory updates Firebase chat record
                Chats.send($scope.user, $scope.IM.textMessage);
                $scope.IM.textMessage = "";
            })
            .catch(function(err){
                debugger;
            });
        });
    };
hashans commented 7 years ago

@bmwertman I'm also facing the same issue. Were you able to find a workaround?

bmwertman commented 7 years ago

I had no success with it. I'm now in progress of switching to the Phonegap plugin. https://github.com/phonegap/phonegap-plugin-push

I find the API to be a little more robust and the documentation is more detailed. It has been going more smoothly but is still not quite working completely.

colorao commented 7 years ago

I've got the same problem. Push is received by the Android device, but always in background mode. If I tap onto it the App opens but onNotification() is never triggered. If the App is in Foreground, the callback also is never triggered....

ilman commented 7 years ago

@colorao I was experiencing the same issue before. Found out it was because I am using firebase console to test to send the notification. Firebase console doesnt have "click_action":"FCM_PLUGIN_ACTIVITY" property in the payload. Try using https://cordova-plugin-fcm.appspot.com/ instead

xardit commented 7 years ago

I tried with "click_action":"FCM_PLUGIN_ACTIVITY" property, with and without custom data values, with and without application open. My app just opens normally like running from a simple click. I need to detect the click is received from the notification ,but the function onNotification() is not solving the problem, i tried to include this function on any angluar run() and on controllers too but still nothing :(

xardit commented 7 years ago

I found the problem, its simple really, the FCMPlugin is not loaded even if you include it at run or controller, the best way to correctly run the onNotification or getToken or other functions of fcm plugin is to put an interval only at your init contoller or at run() since i'm using ionic, in my example this interval gets clear making the script run only once on each app run:

if(typeof check_fcm_loaded==='undefined'){
        var check_fcm_loaded = setInterval(function(){
            if(typeof FCMPlugin!=='undefined'){
                var regToken = function(registeredToken){
                    setTimeout(function(){
                        // alert(registeredToken);
                        // console.log(registeredToken);
                        // new token received
                        if( localStorage.token && localStorage.token != registeredToken // its a new token
                          && localStorage.instance ){
                              var newToken = {token: registeredToken, instance: localStorage.instance};
                              $http.post($rootScope.srv + '?newToken=1', newToken, $rootScope.httpConfig).then(function successCallback(response) {
                                // response.data
                              }, function errorCallback(response) {
                                // alert('no internet connecton probably!')
                              });
                        }
                        localStorage.token = registeredToken;
                    }, 4000);
                };
                var errRegToken = function(err){
                    console.log('error retrieving token: ' + err);
                }

                FCMPlugin.getToken(regToken, errRegToken);
                FCMPlugin.onTokenRefresh(regToken, errRegToken);

                FCMPlugin.onNotification(function(data){
                    alert('notification clicked YAYYY');
                    if(data.wasTapped){
                        alert('notification clicked YAYYY #2');
                      //Notification was received on device tray and tapped by the user.
                      // alert( JSON.stringify(data) );
                    }else{
                      //Notification was received in foreground. Maybe the user needs to be notified.
                      // alert( JSON.stringify(data) );
                    }
                    // open the search filtered by topic
                    if(localStorage.interes){
                        // localStorage.interes
                        localStorage.interesNotification=true;
                        $state.go('app.search');
                    }
                }, function(msg){ // function registered successfuly
                    // alert(msg); // typically msg='OK'
                }, function(err){
                    console.log(err);
                });
                clearInterval(check_fcm_loaded);
            }
        }, 2000);
    }
LordDraagonLive commented 6 years ago

image This how the FCMPlugin was declared back in the day when we had declarations.d.ts. However, now we don't have a declarations.d.ts file in ionic. Therefore, how can we declare it? I didn't find any solutions yet.

I think I found out that you can declare it on the top of the ts file you need the declaration just below the imports.