Search code examples
ionic-frameworkionic-cloud

Ionic Cloud Push GCM Notifications Not Received


I don't understand the Ionic Cloud docs make this sound sooo easy, but I can't seem to receive push notifications. It registers when the application starts up, but after that notifications sent from the Ionic Cloud dashboard are never received. I have spent hours trying to find some key word that I missed in the docs. I also reviewed the FAQ, and took the second point into consideration by sending a second notification with the application closed, and each time the status is sent, but that said I should still have received the first notification in the application.

I'm sending the notifications to all users, but we're not using Ionic Clouds Auth service so I'm not sure how the notifications are directed since there are no users just a registered device that has the application loaded using ionic run android.

Using a clean install of Ionic 1.3.1 I've done the bare minimum to receive a notification based on the docs, can anyone see where I might have stepped wrong? It is just basically the base setup with a controller to listen for the notification.

Following the Ionic docs step-by-step. I remade the application completely just to write this question using these exact steps.

  1. npm install @ionic/cloud --save
  2. cp node_modules/@ionic/cloud/dist/bundle/ionic.cloud.min.js www/lib
  3. Add cloud JS file to index.html, which I'll post below)
  4. Don't need bluebird for promises
  5. ionic io init creates app in dashboard, and set app_id in ionic.config.json, which I'll post below
  6. Added config block, which I'll post below, and jumped to Push services
  7. Had to set up GCM since FCM is not available in Ionic Cloud Dashboard due to some issues
  8. Added a security profile to the application using the Ionic Cloud dashboard in Certificates
  9. Added the GCM credentials to the development security profile
  10. Added phonegap-plugin-push using cordova plugin add phonegap-plugin-push --variable SENDER_ID=123456789011 --save, and checked SENDER_ID is in config.xml, where SENDER_ID is the project number
  11. Added ionic.cloud as dependency to module
  12. Added run for registering the device token, which I'll post below
  13. Created a temp controller just for testing since this is Angular 1.5 and you can just create a component now, and added the $scope.$on listener, which I'll post below
  14. Ran ionic run and loaded the application onto my phone, which when running inspector on the app I can see it is registering on open and I get a token
  15. Then onto the Ionic Cloud dashboard and sent a notification, which is never received

NOTE: The APP_ID, SENDER_ID, API_KEYS, etc have all be substituted for randomly equivalent numbers for this example

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

    <!-- TODO: Add brand of application -->
    <title></title>

    <link rel="manifest" href="manifest.json">

    <!-- un-comment this code to enable service worker
    <script>
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('service-worker.js')
          .then(() => console.log('service worker installed'))
          .catch(err => console.log('Error', err));
      }
    </script>-->


    <!-- Compiled Styles -->
    <!-- inject:css -->
    <link href="css/ionic.app.css" rel="stylesheet">
    <!-- endinject -->

    <!-- Ionic Scripts -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script src="lib/ionic.cloud.min.js"></script>

    <!-- Google Maps API -->
    <!--<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDOCZ0kgg2rTRzmGepWQMu6EM90koX4mUs&amp;libraries=places"></script>-->

    <!-- Vendor Scripts -->
    <!-- bower:js -->
    <!-- endbower -->

    <!-- Cordova Script (this will be a 404 during development) -->
    <script src="lib/ngCordova/dist/ng-cordova.js"></script>
    <script src="cordova.js"></script>

    <!-- Compiled Scripts -->
    <!-- inject:js -->
    <script src="js/app.module.js"></script>
    <script src="js/app.cloud.js"></script>
    <script src="js/app.config.js"></script>
    <script src="js/app.constants.js"></script>
    <script src="js/app.controller.js"></script>
    <!-- endinject -->
    <!-- inject:templates:js -->
    <!-- endinject -->
</head>
<body ng-app="app">

<ion-pane>
    <ion-header-bar class="bar-stable" ng-controller="AppController">
        <h1 class="title">Ionic Blank Starter</h1>
    </ion-header-bar>
    <ion-content>
    </ion-content>
</ion-pane>

</body>
</html>

app.module.js

(function () {

  'use strict';

  var dependencies = [
    'ionic',
    'ionic.cloud',
    'ngCordova'
  ];

  function run($ionicPlatform) {

    $ionicPlatform.ready(function () {

      if (window.cordova && window.cordova.plugins.Keyboard) {

        // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
        // for form inputs)
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

        // Don't remove this line unless you know what you are doing. It stops the viewport
        // from snapping when text inputs are focused. Ionic handles this internally for
        // a much nicer keyboard experience.
        cordova.plugins.Keyboard.disableScroll(true);
      }

      if (window.StatusBar) {
        StatusBar.styleDefault();
      }
    });
  }

  run.$inject = [
    '$ionicPlatform'
  ];

  angular
      .module('app', dependencies)
      .run(run);

})();

app.cloud.js

(function () {

    'use strict';

    function config($ionicCloudProvider) {

        $ionicCloudProvider.init({
            'core': {
                'app_id': '1234ab12'
            },
            'push': {
                'sender_id': '123456789011',
                'pluginConfig': {
                    'ios': {
                        'badge': true,
                        'sound': true
                    },
                    'android': {
                        'iconColor': '#343434',
                        'sound': true,
                        'vibrate': true
                    }
                }
            }
        });
    }

    config.$inject = [
        '$ionicCloudProvider'
    ];

    function run($ionicPush) {

        // Register every time the application is opened so the device is
        // guaranteed to be registered and ready for notifications
        $ionicPush
            .register()
            .then(function (token) {

                // Save the generated device token with the current user when
                // the token is saved
                return $ionicPush.saveToken(token);
            })
            .then(function (device) {

                console.log('Device token:', device.token);
            });
    }

    run.$inject = [
        '$ionicPush'
    ];

    angular
        .module('app')
        .config(config)
        .run(run);

})();

ionic.config.json

{
  "name": "v1.3",
  "app_id": "1234ab12",
  "gulpStartupTasks": [
    "sass",
    "watch"
  ],
  "watchPatterns": [
    "www/**/*",
    "!www/lib/**/*",
    "!www/**/*.map"
  ]
}

config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.ionicframework.v13169294" version="0.0.1" 

    // ...

    <plugin name="phonegap-plugin-push" spec="~1.8.2">
        <variable name="SENDER_ID" value="123456789011" />
    </plugin>
</widget>

.io.config.json

{"app_id":"1234ab12","api_key":"e38rj3i3jsofp3098e8djksod92dmdow0ekdsj2930dk300f"}

app.controller.js

(function () {

    'use strict';

    function AppController($scope) {

        var vm = this;

        // ---
        // PUBLIC METHODS.
        // ---

        $scope.$on('cloud:push:notification', function (event, data) {
            var msg = data.message;
            alert(msg.title + ': ' + msg.text);
        });

        // ---
        // PRIVATE METHODS.
        // ---
    }

    AppController.$inject = [
        '$scope'
    ];

    angular
        .module('app')
        .controller('AppController', AppController);

})();

Solution

  • Okay, everything I setup in the question is correct. What is NOT correct is the Ionic Dashboard, which is asking for a GCM API key in the security profile, and instead it turns out you need to create a FCM project and use the Server key in the GCM API key input field.

    Thanks to this post on Ionics Forums - https://forum.ionicframework.com/t/ionic-push-notification-for-android-keeps-giving-me-error-gcm-invalid-auth/63041/8.

    I also posted a issue on Ionic Cloud's github repo - https://github.com/driftyco/ionic-cloud-issues/issues/198#issuecomment-250856824