问题
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:
- The code for push notifications is written inside the buzon_page controller, which is the page that is having trouble.
- 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.
- 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:
- It shows a "ReferenceError: options is not defined" at factorys.js
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
回答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');
});
回答2:
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.
回答3:
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
来源:https://stackoverflow.com/questions/30516020/ionic-page-transition-not-working-to-page-with-push-feature