1

I implemented android push reception in my app, and it works well as long as the app starts at that page. But if you navigate to the inbox page where the push notifications are implemented the transition doesn't work.

The transition worked well without the push implementation.

I wonder if someone has had a similar problem implementing features.

.controller('BuzonMenuCtrl', function($scope, $window, $state, $ionicPlatform) {
  $scope.botonBuzon = function(){
    $state.go('buzon');
  };
})

.controller('BuzonCtrl', function($scope, $rootScope, $window, $ionicActionSheet, $ionicPopup, $state, $http, dataFactory, pushFactory) {

  // Activacion de la funcionalidad push
  pushFactory.funcionalidadPush();

}

factorys.js

.factory('pushFactory', ['$rootScope','$http','$state','$ionicLoading','$ionicPlatform','$cordovaPush','dataFactory',
                          function($rootScope,$http,$state,$ionicLoading,$ionicPlatform,$cordovaPush,dataFactory) {

  /* Objeto del factory */
  var fac = {};

  fac.funcionalidadPush = function(){
    if (ionic.Platform.isAndroid()){
      var androidConfig = {
        "senderID": "94XXXXXXXXXX",
        "ecb": "casosPush"
      };

      $rootScope.data.pushplatform = "gcm";
      alert('Entro en modo Android');

    };

    if (ionic.Platform.isIOS()){
      alert('Entro en modo iOS');
    };

    $ionicPlatform.ready(function() {
      $cordovaPush.register(androidConfig).then(function(result) {
        // Success
      }, function(err) {
        // Error
      })

      window.casosPush = function (notification) {
        switch(notification.event) {
          case 'registered':
            if (notification.regid.length > 0 ) {
              alert('registration ID = ' + notification.regid);
              $rootScope.data.token = notification.regid;

            }
            break;

          case 'message':
            // this is the actual push notification. its format depends on the data model from the push server
            //alert('message = ' + notification.message + ' msgCount = ' + notification.msgcnt);
            $rootScope.mensajes.push(notification);
            break;

          case 'error':
            alert('GCM error = ' + notification.msg);
            break;

          default:
            alert('An unknown GCM event has occurred');
            break;
        }
      };

      // WARNING: dangerous to unregister (results in loss of tokenID)
      $cordovaPush.unregister(options).then(function(result) {
        // Success!
      }, function(err) {
              // Error
      })

    }, false);
  };


  return fac;

}]);

App.js

angular.module('notPush', ['ionic', 'ngCordova', 'notPush.controllers'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider

  .state('splash', {
    url: '/splash',
    templateUrl: 'templates/splash.html',
    controller: 'SplashCtrl'
  })

  .state('buzonMenu', {
    url: '/buzonMenu',
    templateUrl: 'templates/buzonMenu.html',
    controller: 'BuzonMenuCtrl'
  })

  .state('buzon', {
    url: '/buzon',
    templateUrl: 'templates/buzon.html',
    controller: 'BuzonCtrl'
  })

  // If none of the above states are matched, use this as the fallback:
  $urlRouterProvider.otherwise('/buzonMenu');

});

EDIT

As suggested in the comments I tried

$window.location.reload(true);

which doesn't do anything except to make the screen blink, and also

$state.go($state.current, {}, {reload: true});

which attemps to reload the page but only in a corrupt state, it loads the white background and the buttons (without color) but nothing else.

EDIT 2 Some clarifications:

  1. The code for push notifications is written inside the buzon_page controller, which is the page that is having trouble.
  2. When I say "the transition doesn't work" I mean that the page doesn't load, but all the alerts of that page are still triggered, and the Push Token is still retrieved. Is a visual problem, the view doesn't load.
  3. The problem is not related to HTTP calls because they are currently commented.

EDIT 3

I moved the notifications code to a factory instead of having it inside the controller (as it should be, I guess) but there is no improvement.

I'm adding the result of adb logcat during the issue. There are 2 things that cought my attention:

  1. It shows a "ReferenceError: options is not defined" at factorys.js
  2. It shows some OpenGLRenderer issue.

    1219             AudioTrack  W  AUDIO_OUTPUT_FLAG_FAST denied by client   
    2531             PushPlugin  V  execute: action=register
    2531             PushPlugin  V  execute: data=[{"senderID":ID DELETED FOR PRIVACY ISSUES,"ecb":"casosPush"}]
    2531             PushPlugin  V  execute: jo={"senderID":ID DELETED FOR PRIVACY ISSUES,"ecb":"casosPush"}
    2531             PushPlugin  V  execute: ECB=casosPush senderID=ID DELETED FOR PRIVACY ISSUES
    2531           GCMRegistrar  D  resetting backoff for ID DELETED FOR PRIVACY ISSUES
    1219   InputMethodManager..  W  Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@df31fbd attribute=null, token = a
                                   ndroid.os.BinderProxy@28f2dc02
    2531           GCMRegistrar  V  Registering app ID DELETED FOR PRIVACY ISSUES of senders ID DELETED FOR PRIVACY ISSUES
    2531   SystemWebChromeCli..  D  file:///android_asset/www/lib/ionic/js/ionic.bundle.js: Line 20243 : ReferenceError: options is not defined
    2531   SystemWebChromeCli..  D  at file:///android_asset/www/js/factorys.js:214:31
    2531   SystemWebChromeCli..  D  at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44687:19
    2531   SystemWebChromeCli..  D  at Object.ionic.Platform.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:2120:9)
    2531   SystemWebChromeCli..  D  at Object.self.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44685:26)
    2531   SystemWebChromeCli..  D  at Object.fac.funcionalidadPush (file:///android_asset/www/js/factorys.js:166:20)
    2531   SystemWebChromeCli..  D  at new <anonymous> (file:///android_asset/www/js/controllers.js:440:15)
    2531   SystemWebChromeCli..  D  at invoke (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:12821:17)
    2531   SystemWebChromeCli..  D  at Object.instantiate (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:12829:27)
    2531   SystemWebChromeCli..  D  at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:17098:28
    2531   SystemWebChromeCli..  D  at self.appendViewElement (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:48110:24)
    2531               chromium  I  [INFO:CONSOLE(20243)] "ReferenceError: options is not defined
    2531               chromium  I  at file:///android_asset/www/js/factorys.js:214:31
    2531               chromium  I  at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44687:19
    2531               chromium  I  at Object.ionic.Platform.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:2120:9)
    2531               chromium  I  at Object.self.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44685:26)
    2531               chromium  I  at Object.fac.funcionalidadPush (file:///android_asset/www/js/factorys.js:166:20)
    2531               chromium  I  at new <anonymous> (file:///android_asset/www/js/controllers.js:440:15)
    2531               chromium  I  at invoke (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:12821:17)
    2531               chromium  I  at Object.instantiate (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:12829:27)
    2531               chromium  I  at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:17098:28
    2531               chromium  I  at self.appendViewElement (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:48110:24)", source: file:///android_asset/www/lib/ionic
                                   /js/ionic.bundle.js (20243)
    1604                    GCM  D  GcmService start Intent { act=com.google.android.c2dm.intent.REGISTER pkg=com.google.android.gms cmp=com.google.android.gms/.gcm.GcmServi
                                   ce (has extras) } com.google.android.c2dm.intent.REGISTER
    2531   GCMBroadcastReceiver  V  onReceive: com.google.android.c2dm.intent.REGISTRATION
    2531           GCMRegistrar  V  Setting the name of retry receiver class to com.plugin.gcm.CordovaGCMBroadcastReceiver
    2531   GCMBroadcastReceiver  V  GCM IntentService class: com.plugin.gcm.GCMIntentService
    2531   GCMBaseIntentService  V  Acquiring wakelock
    2531   GCMBaseIntentService  V  Intent service name: GCMIntentService-GCMIntentService-1
    2531           GCMRegistrar  V  Registering receiver
    2531   GCMBaseIntentService  D  handleRegistration: registrationId = TOKEN DELETED FOR PRIVACY ISSUES, error = null, unregistered = null
    2531           GCMRegistrar  D  resetting backoff for ID DELETED FOR PRIVACY ISSUES
    2531           GCMRegistrar  V  Saving regId on app version 10
    2531       GCMIntentService  V  onRegistered: TOKEN DELETED FOR PRIVACY ISSUES
    2531       GCMIntentService  V  onRegistered: {"event":"registered","regid":TOKEN DELETED FOR PRIVACY ISSUES}
    2531             PushPlugin  V  sendJavascript: javascript:casosPush({"event":"registered","regid":TOKEN DELETED FOR PRIVACY ISSUES})
    2531   GCMBaseIntentService  V  Releasing wakelock
    2531          EGL_emulation  W  eglSurfaceAttrib not implemented
    2531         OpenGLRenderer  W  Failed to set EGL_SWAP_BEHAVIOR on surface 0xa4cdd7e0, error=EGL_SUCCESS
    1219             AudioTrack  W  AUDIO_OUTPUT_FLAG_FAST denied by client
    1219   InputMethodManager..  W  Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@35215d0a attribute=null, token = 
                                   android.os.BinderProxy@28f2dc02
    
David Prieto
  • 2,239
  • 4
  • 32
  • 51
  • This is not a plugin issue! Read this [answer](http://stackoverflow.com/a/25206754/1761793) – Ajoy May 29 '15 at 06:42
  • It is a plugin issue because Cordova's push notification plugin is the one giving me a headache. And thank you for your suggestion but unfortunely it doesn't work. I will edit the question with the results. – David Prieto May 29 '15 at 19:49
  • (My bad. I assumed wrong, let's start again) What do you mean by _the page where push notifications are implemented_? Is not the PN registration in `platformReady`? If there is something more, update your post with the relevant code. Also when you say _the transition doesn't work_, are there any errors? – Ajoy May 30 '15 at 02:20
  • 1) _"the page where push notifications are implemented"_ The code for push notifications is written inside the **buzon_page** controller. 2) _"the transition doesn't work"_ means that the page doesn't load, but all the alerts of that page are still triggered. @Ajoy – David Prieto Jun 01 '15 at 14:33
  • You should run the plugin [register as soon as the device is ready](https://github.com/phonegap-build/PushPlugin#register). Move all the plugin init code from `BuzonCtrl` to `.run` in app.js – Ajoy Jun 01 '15 at 14:47
  • @Ajoy for that is the `$ionicPlatform.ready(function() {`. Nevertheless I tried to do what you say but the app doesn't even run when I did. I don't think you can put stuff in there. I modified the code, I'm editing the question now. – David Prieto Jun 02 '15 at 20:59
  • 1
    See this [gist](https://gist.github.com/ajoyoommen/98da763cc1379fbae363). This is a file from a live project. (Changed a few names and senderID). The idea is that the plugin must register and wait for new messages as soon as the app starts. That will prevent errors like: a notification is received but the plugin is not yet ready to process or accept it. – Ajoy Jun 03 '15 at 05:42
  • 1
    Another tip: Use alerts to find the exact line after which alerts stop or transition fails. It might help you spot the issue. – Ajoy Jun 03 '15 at 05:47
  • 1
    @Ajoy thank you very much, I posted your suggestion as the answer. It fixed the problem. – David Prieto Jun 03 '15 at 16:26

3 Answers3

1

I solved the problem thanks to the help in the comments, so I'm going to write the solution here.

The comment suggested this code so that the push notifications were activated as soon as the app starts.

I'll add here my own code just in case, the alerts and $rootScope variables are for testing purposes.

/* 
   app.js
*/
angular.module('notPush', ['ionic', 'notPush.controllers', 'notPush.factorys'])

.run(function($ionicPlatform,$rootScope) {
  $ionicPlatform.ready(function() {

    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }

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

    $rootScope.mensajes = [];

    // Push code
    try{
      var pushNotification = window.plugins.pushNotification;
    } catch (ex){

    }
    var successfn = function(result){
      alert("Success: " + result);
    };
    var errorfn   = function(result){
      window.alert("Error: " + result);
    };
    window.casosPush = function(notification){
      switch (notification.event){
        case 'registered':
          if (notification.regid.length > 0){
            alert('registration ID = ' + notification.regid);
          }
          break;

        case 'message':
          alert(JSON.stringify([notification]));
          $rootScope.mensajes.push(notification);
          break;

        case 'error':
          alert('GCM error = ' + notification.msg);
          break;

        default:
          alert('An unknown GCM event has occurred');
          break;
      }
    };
    try{
      pushNotification.register(
        successfn,
        errorfn,
        {
          "senderID": "94XXXXXXXXXX",
          "ecb"     : "window.casosPush"
        }
      );
    } catch(notification){

    } 
  });
})

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider

  .state('splash', {
    url: '/splash',
    templateUrl: 'templates/splash.html',
    controller: 'SplashCtrl'
  })

  .state('registro', {
    url: '/registro',
    templateUrl: 'templates/registro.html',
    controller: 'RegistroCtrl'
  })

  .state('buzonMenu', {
    url: '/buzonMenu',
    templateUrl: 'templates/buzonMenu.html',
    controller: 'BuzonMenuCtrl'
  })

  .state('buzon', {
    url: '/buzon',
    templateUrl: 'templates/buzon.html',
    controller: 'BuzonCtrl'
  })

  .state('detallesSimple', {
    url: '/detallesSimple',
    templateUrl: 'templates/detallesSimple.html',
    controller: 'DetallesCtrl'
  })

  .state('detallesDoble', {
    url: '/detallesDoble',
    templateUrl: 'templates/detallesDoble.html',
    controller: 'DetallesCtrl'
  })

  .state('detallesWV', {
    url: '/detallesWV',
    templateUrl: 'templates/detallesWV.html',
    controller: 'DetallesWVCtrl'
  })

  // If none of the above states are matched, use this as the fallback:
  $urlRouterProvider.otherwise('/splash');

});
David Prieto
  • 2,239
  • 4
  • 32
  • 51
1

A sample code from a working Ionic project. As an example for how PushPlugin should be initialized.

var exapp = angular.module('exapp',
                  ['ionic',
                   'ui.select2',
                   'exapp.controllers',
                   'exapp.services']);

exapp.run(function($ionicPlatform, $state, Notifications, geo) {
    $ionicPlatform.ready(function() {
    try{
        var pushNotification = window.plugins.pushNotification;
    } catch (ex){

    }
    var successfn = function(result){
        // window.alert("S: " + result);
    };
    var errorfn   = function(result){
        // window.alert("E: " + result);
    };
    window.onCB = function(e){
        switch (e.event){
        case 'registered':
        if (e.regid.length > 0){
            localStorage.setItem('registration_id', e.regid);
        }
        break;
        case 'message':
        if (e.foreground){
            navigator.notification.beep(1);
        }
        $state.go('app.notifications');
        break;
        }
    };
    try{
        pushNotification.register(
        successfn,
        errorfn,
        {
            "senderID": "191919191919191",
            "ecb"     : "window.onCB"
        }
        );
    } catch(e){

    }
    });
});

// States
exapp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider

    .state('app', {
        url: "/app",
        abstract: true,
        templateUrl: "templates/menu.html",
        controller: 'AppCtrl'
    })

    .state('app.profile', {
        url: "/profile",
        views: {
        'menuContent': {
            templateUrl: "templates/profile.html",
            controller: "ProfileCtrl"
        }
        }
    })

    .state('app.login', {
        url: "/login",
        views: {
        'menuContent' :{
            templateUrl: "templates/login.html",
            controller: 'AuthCtrl'
        }
        }
    });

    // if none of the above states are matched, use this as the fallback
    $urlRouterProvider.otherwise('/app/profile');
});

Provided here just in case the gist becomes unavailable.

Ajoy
  • 1,838
  • 3
  • 30
  • 57
0

I had similar problem in my app when i was trying to make a REST call at the same time of view transition. this is because $http promise is interrupting view rendering. This can be taken care of if you wrap your $http call in $timeout because $timeout with no time mentioned will put your $http in queue rather than interrupting current task.

you can do something like

$scope.$on('$cordovaPush:notificationReceived', handleNotification);

handleNotification = function(event, notification){
    $timeout(function(event, notification) {
            switch(notification.event) {
                case 'registered':
                    if (notification.regid.length > 0 ) {
                        alert('registration ID = ' + notification.regid);
                        $scope.regid = notification.regid;
                        var user = { user: 'David', type: 'android', token: notification.regid };
                        $http.post('http://172.16.16.101:8000/tokens', JSON.stringify(user));
                    }
                    break;

                case 'message':
                    // this is the actual push notification. its format depends on the data model from the push server
                    //alert('message = ' + notification.message + ' msgCount = ' + notification.msgcnt);
                    alert(JSON.stringify([notification]));
                    var aux = {title:'',message:'',payload: { valor1:true }}
                    $scope.mensajes.push(notification);
                    break;

                case 'error':
                    alert('GCM error = ' + notification.msg);
                    break;

                default:
                    alert('An unknown GCM event has occurred');
                    break;
            }
        });
}

this is a rough idea that you have to fix and refine to fit your need

Gurbakhshish Singh
  • 1,034
  • 1
  • 10
  • 25