开发者问题收集

Ionic 页面转换无法转换到具有推送功能的页面

2015-05-28
1582

我在我的应用中实现了 Android 推送接收,只要应用从该页面启动,它就能正常工作。但是,如果您导航到实现推送通知的收件箱页面,转换将不起作用。

即使没有实现推送,转换也能正常工作。

我想知道是否有人在实现功能时遇到过类似的问题。

.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');

});

编辑

正如评论中所建议的,我尝试了

$window.location.reload(true);

除了使屏幕闪烁之外什么也不做,而且

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

尝试重新加载页面但仅在损坏状态下,它加载了白色背景和按钮(没有颜色),但没有其他内容。

编辑 2 一些说明:

  1. 推送通知的代码写在 buzon_page 控制器内,该控制器是具有麻烦。
  2. 当我说 “转换不起作用” 时,我的意思是页面没有加载,但该页面的所有警报仍被触发,并且仍会检索推送令牌。这是一个视觉问题,视图不会加载。
  3. 问题与 HTTP 调用无关,因为它们目前已被注释。

编辑 3

我将通知代码移至工厂,而不是将其放在控制器内(我猜应该是这样),但没有任何改进。

我在问题期间添加了 adb logcat 的结果。有两件事引起了我的注意:

  1. 它在 factorys.js 上显示“ReferenceError:未定义选项”
  2. 它显示了一些 OpenGLRenderer 问题。

    1219 AudioTrack W AUDIO_OUTPUT_FLAG_FAST 被客户端拒绝
    2531 PushPlugin V 执行:action=register
    2531 PushPlugin V 执行:data=[{"senderID":ID DELETED FOR PRIVACY ISSUES,"ecb":"casosPush"}]
    2531 PushPlugin V 执行:jo={"senderID":ID DELETED FOR PRIVACY ISSUES,"ecb":"casosPush"}
    2531 PushPlugin V 执行:ECB=casosPush senderID=ID DELETED FOR PRIVACY ISSUES
    2531 GCMRegistrar D 重置 ID DELETED FOR PRIVACY 的退避问题
    1219 InputMethodManager.. W 窗口已获得焦点,忽略焦点增益:com.android.internal.view.IInputMethodClient$Stub$Proxy@df31fbd attribute=null, token = a
    ndroid.os.BinderProxy@28f2dc02
    2531 GCMRegistrar V 注册应用程序 ID 因隐私问题已删除 发送者 ID 因隐私问题已删除
    2531 SystemWebChromeCli.. D file:///android_asset/www/lib/ionic/js/ionic.bundle.js:第 20243 行:ReferenceError:未定义选项
    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 在 Object.ionic.Platform.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:2120:9)
    2531 SystemWebChromeCli.. D 在 Object.self.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44685:26)
    2531 SystemWebChromeCli.. D 在 Object.fac.funcionalidadPush (file:///android_asset/www/js/factorys.js:166:20)
    2531 SystemWebChromeCli.. D 在 new <anonymous> (文件:///android_asset/www/js/controllers.js:440:15)
    2531 SystemWebChromeCli.. D 在调用 (文件:///android_asset/www/lib/ionic/js/ionic.bundle.js:12821:17)
    2531 SystemWebChromeCli.. D 在 Object.instantiate (文件:///android_asset/www/lib/ionic/js/ionic.bundle.js:12829:27)
    2531 SystemWebChromeCli.. D 在文件:///android_asset/www/lib/ionic/js/ionic.bundle.js:17098:28
    2531 SystemWebChromeCli.. D 在 self.appendViewElement (文件:///android_asset/www/lib/ionic/js/ionic.bundle.js:48110:24)
    2531 chromium I [INFO:CONSOLE(20243)] “ReferenceError:未定义选项
    2531 chromium I 位于 file:///android_asset/www/js/factorys.js:214:31
    2531 chromium I 位于 file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44687:19
    2531 chromium I 位于 Object.ionic.Platform.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:2120:9)
    2531 chromium I 位于 Object.self.ready (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:44685:26)
    2531 chromium I 位于 Object.fac.funcionalidadPush (file:///android_asset/www/js/factorys.js:166:20)
    2531 chromium I 在 new <anonymous> (file:///android_asset/www/js/controllers.js:440:15)
    2531 chromium I 在invoke (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:12821:17)
    2531 chromium I 在 Object.instantiate (file:///android_asset/www/lib/ionic/js/ionic.bundle.js:12829:27)
    2531 chromium I 在 file:///android_asset/www/lib/ionic/js/ionic.bundle.js:17098:28
    2531 chromium I 在 self.appendViewElement (file
3个回答

在评论的帮助下,我解决了这个问题,所以我将在这里写下解决方案。

评论建议使用此 代码 ,以便在应用启动时立即激活推送通知。

我将在这里添加我自己的代码以防万一,警报和 $rootScope 变量用于测试目的。

/* 
   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
2015-06-03

来自正在运行的 Ionic 项目的示例代码。作为如何初始化 PushPlugin 的示例。

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');
});

在此提供以防要点不可用。

Ajoy
2015-06-04

当我尝试在视图转换的同时进行 REST 调用时,我的应用程序中也遇到了类似的问题。这是因为 $http 承诺正在中断视图渲染。如果您将 $http 调用包装在 $timeout 中,则可以解决这个问题,因为未提及时间的 $timeout 会将您的 $http 放入队列中,而不是中断当前任务。

您可以执行类似操作

$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;
            }
        });
}

这是一个粗略的想法,您必须对其进行修复和改进以满足您的需求

Gurbakhshish Singh
2015-05-29