How to integrate Cordova/Phonegap plugins within Angular/Ionic the right way?


#1

I have a question about integrating Cordova/Phonegap plugins within my Ionic project.

I’m using the PushPlugin and the Local Notifications plugin. I’m unsure as to what would be the right, Angular / Ionic approved way to initialise and use these plugins in the app. My question isn’t specific to these plugins per se but apply to all PG plugins.

Should I initialise plugins in the $ionicPlatform.ready function? I currently have $ionicPlatform.ready tied to my home controller, but that means they will be called every time a user views the home screen so that can’t be right.

Any advice?


Can anyone who has integrated phonegap plugins with Ionic share the git repo?
#2

Hey @coen_warmer, a good way to do this is to use the run function:

angular.module('myModule', ['ionic'])
.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Initialize plugin here
  });
});

Does that help?


deviceReady how to
$ionicPlatform.ready() Where can i read about on doc?
#3

I’m having trouble getting the notification back of a successful registration using PushPlugin. I tested it without ionic and angular, so I know that it is sending the notification, but when I put the code into the $ionicPlatform.ready code like Max states about I can’t get the notification to be heard.

Anyone have a recommendation or some working code they could show?


#4

I haven’t dealt with push notifications before; so I may not be of much value. Are you sure this is not a matter of the asynchronous nature of most PhoneGap operations? Since they occur outside of the AngularJS digest cycle, you may not see the results. Perhaps wrap your result in $rootScope.$apply ?


#5

BTW, is there any difference to use $ionicPlatform.ready or ionic.Platform.ready?


#6

Maybe,

I would create some method:

isScopeInCycle = function () {
        return $rootScope.$root.$$phase != '$apply' && $rootScope.$root.$$phase != '$digest';
}

and use:

 if(isScopeInCycle()){/*   */} 

#7

I’m using pushplugin

Here is what I was trying:

angular.module(‘appName.services’, [])

.run(function($ionicPlatform){

    $ionicPlatform.ready(function($scope, $window){
              var pushNotification;
            pushNotification = window.plugins.pushNotification;
            pushNotification.register(successHandler, errorHandler,{"senderID":"**myGCMid**","ecb":"onNotificationGCM"});		// required!

}

I can put the successHandler and the errorHandler functions in this same place and they work fine. But the onNotificationGCM callback only works if I put it above my angular code making my code look like this:


function onNotificationGCM (e){
alert(‘push message’+e);
}

angular.module(‘appName.services’, [])


I’ve tried window.onNotificationGCM to try to get the callback and $window.onNotificationGCM, but they don’t seem to work. I’ve trying changing the callback to functions inside angular using $rootScope.onNotificationGCM and $scope.onNotificationGCM, but they also don’t work.


#8

Did you try variations of $apply ?

Like :

function safeApply( fn ) {
    if( !$rootScope.$$phase ) {
        $rootScope.$apply(fn);
    } else {
        fn();
}

function onNotificationGCM (e){
    alert('push message'+e);
}

safeApply( onNotification(e));

FYI : See also : Possible Cordova/KitKat Bug with Camera Plugin. Anyone Else?


#9

Has anyone documented the correct way to do this.
I am in the process of adding push to my app and would appreciate any help

Thanks


#10

I’m using the following code to bridge from the global function to an angular service:

window.onNotificationGCM = function (event) {
    var pushService = angular.element(document.querySelector('body')).injector()
        .get('PushNotification');
    pushService.onNotificationGCM(event);
};

But perhaps there is a better way to do so?
Edit: add


      

Change angular state after push reception
#11

Someone is putting together a repo for this.


#12

Here’s the way I did it using the PushPlugin. http://intown.biz/2014/04/11/android-notifications/. It probably includes some information you already know, but I was trying to be complete. Maybe there’s some helpful code here.


#13

Anyone have a complete example? I have tried to used this example http://intown.biz/2014/04/11/android-notifications/ but it doesn´t work.

This is my app.js code:

    function onNotificationGCM(e) {
    console.log('EVENT -> RECEIVED:' + e.event + '');
    switch( e.event )
    {
        case 'registered':
            if ( e.regid.length > 0 )
            {
                console.log('REGISTERED with GCM Server -> REGID:' + e.regid + "");
 
                //call back to web service in Angular.  
                var elem = angular.element(document.querySelector('[ng-app]'));
                var injector = elem.injector();
                var myService = injector.get('PushProcessingService');
                myService.registerID(e.regid);
                elem.scope().$apply();
            }
            break;
 
        case 'message':
            // if this flag is set, this notification happened while we were in the foreground.
            // you might want to play a sound to get the user's attention, throw up a dialog, etc.
            if (e.foreground)
            {
                //we're using the app when a message is received.
                console.log('--INLINE NOTIFICATION--' + '');
 
                // if the notification contains a soundname, play it.
                //var my_media = new Media("/android_asset/www/"+e.soundname);
                //my_media.play();
                alert(e.payload.message);
            }
            else
            {   
                // otherwise we were launched because the user touched a notification in the notification tray.
                if (e.coldstart)
                    console.log('--COLDSTART NOTIFICATION--' + '');
                else
                    console.log('--BACKGROUND NOTIFICATION--' + '');
 
                // direct user here:
                window.location = "#/tab/featured";
            }
 
            console.log('MESSAGE -> MSG: ' + e.payload.message + '');
            console.log('MESSAGE: '+ JSON.stringify(e.payload));
            break;
 
        case 'error':
            console.log('ERROR -> MSG:' + e.msg + '');
            break;
 
        default:
            console.log('EVENT -> Unknown, an event was received and we do not know what it is');
            break;
    }
}


angular.module('myApp', ['ionic'])

.run(function($ionicPlatform,PushProcessingService){
  $ionicPlatform.ready(function(){
    
    PushProcessingService.initialize();

    PushProcessingService.registerID();

  });
})

.factory('PushProcessingService', function() {
        function onDeviceReady() {
            console.info('NOTIFY  Device is ready.  Registering with GCM server');
            //register with google GCM server
            var pushNotification = window.plugins.pushNotification;
            pushNotification.register(gcmSuccessHandler, gcmErrorHandler, {"senderID":gcmAppID,"ecb":"onNotificationGCM"});
        }
        function gcmSuccessHandler(result) {
            console.info('NOTIFY  pushNotification.register succeeded.  Result = '+result)
        }
        function gcmErrorHandler(error) {
            console.error('NOTIFY  '+error);
        }
        return {
            initialize : function () {
                console.info('NOTIFY  initializing');
                document.addEventListener('deviceready', onDeviceReady, false);
            },
            registerID : function (id) {
                //Put code for the Notifion Server here.  For example:
                myService.registerID(regid).then(function(response){
                    if (response.data.Result) {
                        console.info('NOTIFY  Registration succeeded');
                    } else {
                        console.error('NOTIFY  Registration failed');
                    }
                });
            }, 
            //unregister can be called from a settings area.
            unregister : function () {
                console.info('unregister')
                var push = window.plugins.pushNotification;
                if (push) {
                    push.unregister(function () {
                        console.info('unregister success')
                    });
                }
            }
        }
    });

In my console, the result is this error:

Uncaught ReferenceError: myService is not defined app.js:91
registerID app.js:91
(anonymous function) app.js:66
(anonymous function) ionic.bundle.js:33051
onPlatformReady ionic.bundle.js:2261
onWindowLoad

What is wrong?


#14

@gdp_fran Please format your code correctly, it is quite difficult to read your code this way.


#15

I am sorry.I have fixed the code.


#16

Hello… nobody knows what is wrong in my code?

Thank you in advance


#17

Hey @gdp_fran, I believe the problem is that you call myService.registerID(regid).then(function(response){ in the return method of PushProcessingService.
But at that point myService is nothing. I can’t debug your code, It is too abstract and unstructured like this. But I would say that you need to either inject the dependency or put myService in a global var (but preferably the fist)

Hope that helps


#18

@bramslob is exactly right. When you receive the callback, you’re outside of Angular. The following four lines are a tricky way to make a call back into your AngularJS code.

               //call back to web service in Angular.  
                var elem = angular.element(document.querySelector('[ng-app]'));
                var injector = elem.injector();
                var myService = injector.get('PushProcessingService');
                myService.registerID(e.regid);

This works for me because in my code I have a factory PushProcessingService with method registerID. This calls back to the notification server - the one which keeps track of everyone’s ID to send them to google.

Unfortunately the code on my blog is just a demonstration of methods - it’s not plug-and-play.


#19

Thanks for all of your help. I have tried several times with your examples but it can´t work for me. This is my codepen: http://cdpn.io/BEkqb .

I took the ionic template and i only include the code example of @mmendelson. Is it correct? Because it doesn´t work.

Thank you


#20

+1 - has this been resolved?