AngularJS Promises and Android 4.2.2 (Samsung) not working: nor resolving nor failing

Hi, I’m developing a ionic app targeting, for now, Android and iOS. The app runs without problem with ionic serve and browser, genymotion and iOS simulator. It does not work using a physical android device, more precisely a Samsung Galaxy Trend Plus GT-S7580 mounting Android 4.2.2 (I cannot root it to install a more updated custom rom, this is my only physical device).

This app doesn’t have a local state, doesn’t have a particular logic, it’s just a simple REST client for an API I developed using PHP and Laravel 5. I don’t have CORS errors (in the emulators the app works great) and the white-list plugin is installed and configured properly (I think I properly configured also the meta tag and ng-csp, but look at my body and head tags and let me know if they are correct).

I’m using ngresource. The same problems is present with pure $http provider. Every time a make a request, i.d. the use is logging using a form to receive an oauth token from my server, the POST or GET request is not resolved nor timeouted: my app doesn’t call the success or error function inside the resource or $http promise and the spinner is loading forever. I put two console.log inside the success and error callbacks, the apps doesn’t run them.

In chrome::inspect there’s no trace of network activity. If I don’t use crosswalk, I can see through adb logcat a null pointer exception and a Fatal signal 11 (SIGSEGV) error every time an http request is made.

My app can’t work even minimally if it can’t do http requests and I’m stuck. I have to finish this work soon or I’ll be in toruble. Can you help me please?

Here you can find all the details:

  • Ionic CLI version: 1.7.0
  • Ionic Framework version: the latest stable one (1.1 I guess)
  • Cordova CLI version: 5.3.3
  • Android Platform version: 4.1.1
  • iOS Platform version: 3.9.1

And I’m using these plugins versions:

  • com.ionic.keyboard 1.0.4 “Keyboard”
  • com.rjfun.cordova.httpd 0.9.2 “CorHttpd”
  • cordova-plugin-camera 1.2.0 “Camera”
  • cordova-plugin-console 1.0.1 “Console”
  • cordova-plugin-crosswalk-webview 1.3.1 “Crosswalk WebView Engine”
  • cordova-plugin-device 1.0.1 “Device”
  • cordova-plugin-file 3.0.0 “File”
  • cordova-plugin-file-transfer 1.3.0 “File Transfer”
  • cordova-plugin-media-capture 1.0.1 “Capture”
  • cordova-plugin-network-information 1.0.1 “Network Information”
  • cordova-plugin-screen-orientation 1.4.0 “Screen Orientation”
  • cordova-plugin-splashscreen 2.1.0 “Splashscreen”
  • cordova-plugin-whitelist 1.0.0 “Whitelist”
  • ionic-plugin-keyboard 1.0.7 “Keyboard”

And this is my config.xml:

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.ionicframework.fillussoclient920328" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>fillusso-client</name>
    <description>
        An Ionic Framework and Cordova project.
    </description>
    <author email="hi@ionicframework" href="http://ionicframework.com/">
        Ionic Framework Team
    </author>
    <content src="index.html" />
    <preference name="webviewbounce" value="false" />
    <preference name="UIWebViewBounce" value="false" />
    <preference name="DisallowOverscroll" value="true" />
    <preference name="android-minSdkVersion" value="17" />
    <preference name="BackupWebStorage" value="none" />
    <preference name="SplashScreen" value="screen" />
    <preference name="AutoHideSplashScreen" value="false" />
    <preference name="SplashScreenDelay" value="300000000" />
    <feature name="StatusBar">
        <param name="ios-package" onload="true" value="CDVStatusBar" />
    </feature>
    <allow-navigation href="*" />
    <access origin="*" subdomains="true" />
    <allow-intent href="*" />
    <platform name="android">
        <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
        <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />
        <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />
        <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" />
        <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" />
        <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" />
        <splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" />
        <splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" />
        <splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" />
        <splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" />
        <splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" />
        <splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" />
        <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" />
        <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" />
        <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" />
        <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" />
        <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" />
        <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" />
    </platform>
    <platform name="ios">
        <icon height="57" src="resources/ios/icon/icon.png" width="57" />
        <icon height="114" src="resources/ios/icon/icon@2x.png" width="114" />
        <icon height="40" src="resources/ios/icon/icon-40.png" width="40" />
        <icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80" />
        <icon height="50" src="resources/ios/icon/icon-50.png" width="50" />
        <icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100" />
        <icon height="60" src="resources/ios/icon/icon-60.png" width="60" />
        <icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120" />
        <icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180" />
        <icon height="72" src="resources/ios/icon/icon-72.png" width="72" />
        <icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144" />
        <icon height="76" src="resources/ios/icon/icon-76.png" width="76" />
        <icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152" />
        <icon height="29" src="resources/ios/icon/icon-small.png" width="29" />
        <icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58" />
        <icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87" />
        <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" />
        <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750" />
        <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242" />
        <splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208" />
        <splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" />
        <splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" />
        <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" />
        <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768" />
        <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640" />
        <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320" />
    </platform>
    <preference name="xwalkVersion" value="14+" />
    <preference name="xwalkCommandLine" value="--disable-pull-to-refresh-effect" />
    <preference name="xwalkMode" value="embedded" />
</widget>

My 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">
    <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <link href="lib/angular/angular-csp.css" rel="stylesheet">

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    <link href="css/ionic.app.css" rel="stylesheet">
    -->

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script src="lib/angular-messages/angular-messages.js"></script>
    <script src="lib/angular-resource/angular-resource.js"></script>
    <script src="lib/localforage/dist/localforage.js"></script>
    <script src="lib/angular-localforage/dist/angular-localForage.js"></script>
    <script src="lib/angular-sanitize/angular-sanitize.js"></script>
    <script src="lib/videogular/videogular.js"></script>
    <script src="lib/videogular-controls/vg-controls.js"></script>
    <script src="lib/videogular-overlay-play/vg-overlay-play.js"></script>
    <script src="lib/videogular-poster/vg-poster.js"></script>
    <script src="lib/videogular-buffering/vg-buffering.js"></script>

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

    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/services.js"></script>

</head>
<body ng-app="starter" ng-csp>
<!--
  The views will be rendered in the <ion-nav-view> directive below
  Templates are in the /templates folder (but you could also
  have templates inline in this html file if you'd like).
-->
<ion-nav-view></ion-nav-view>
</body>
</html>

My app.js

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'ngCordova', 'starter.controllers', 'starter.services', 'ngMessages',
    'ngResource', 'LocalForageModule', "ngSanitize", "com.2fdevs.videogular", "com.2fdevs.videogular.plugins.controls",
    "com.2fdevs.videogular.plugins.overlayplay", "com.2fdevs.videogular.plugins.poster"])

    .run(function ($ionicPlatform, $cordovaSplashscreen, $state, loginService, $rootScope, $ionicLoading,
                   $ionicHistory, $localForage, $ionicPopup) {
        $ionicPlatform.ready(function () {
            // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
            // for form inputs)
            if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
                cordova.plugins.Keyboard.disableScroll(true);
            }

            if (window.StatusBar) {
                // org.apache.cordova.statusbar required
                StatusBar.styleLightContent();
            }

            //Imposto variabili globali
            $localForage.setItem('clientSecret', 'cicciopasticcio').then(function() {
                $localForage.getItem('clientSecret').then(function(clientSecret) {
                    loginService.setClientSecret(clientSecret);
                })
            });
            $localForage.setItem('clientId', 'cordova-app').then(function() {
                $localForage.getItem('clientId').then(function(clientId) {
                    loginService.setClientId(clientId);
                })
            });
            //

            //Nascondo la Splash Screen
            setTimeout(function () {
                $cordovaSplashscreen.hide()
            }, 2000);

            //Loading splash screen
            $rootScope.$on('loading:show', function () {
                console.log("CICCIO: RICHIESTA ON");
                $ionicLoading.show({
                    template: '<div>Attendi per favore ...</div> <br><br> <div><ion-spinner></ion-spinner></div>'
                })
            });

            //Registrazione di tutti gli eventi
            $rootScope.$on('loading:hide', function () {
                console.log("CICCIO: RICHIESTA OFF");
                $ionicLoading.hide();
            });

            $rootScope.$on('logout', function () {
                $ionicHistory.nextViewOptions({
                    disableAnimate: false,
                    disableBack: true
                });

                $ionicLoading.hide();
                $state.go('login');
            });

            $rootScope.$on('$cordovaNetwork:online', function(event, networkState){
                if (!loginService.isLogged()) {
                    $ionicHistory.nextViewOptions({
                        disableAnimate: false,
                        disableBack: true
                    });

                    $state.go('login');
                } else {
                    $ionicHistory.nextViewOptions({
                        disableAnimate: false,
                        disableBack: true
                    });

                    $state.go('home');
                }
            });

            $rootScope.$on('$cordovaNetwork:offline', function(event, networkState){
                $ionicHistory.nextViewOptions({
                    disableAnimate: false,
                    disableBack: true
                });

                $state.go('offline');
            });
            //

            $rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
                $ionicPopup.alert({
                    title: 'Errore',
                    template: error,
                    okText: 'Chiudi',
                    okType: 'button button-assertive'
                });
            });
        });
    })

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

        // Ionic uses AngularUI Router which uses the concept of states
        // Learn more here: https://github.com/angular-ui/ui-router
        // Set up the various states which the app can be in.
        // Each state's controller can be found in controllers.js
        $stateProvider

            .state('home', {
                url: "/home",
                cache: false,
                templateUrl: "templates/home.html",
                controller: "HomeCtrl",
                resolve: {
                    item: function(loginService, $localForage) {
                        return $localForage.getItem('token').then(function(token) {
                            loginService.setToken(token);

                            return $localForage.getItem('refreshToken').then(function(refreshToken) {
                                loginService.setRefreshToken(refreshToken);

                                return $localForage.getItem('clientSecret').then(function(clientSecret) {
                                    loginService.setClientSecret(clientSecret);

                                    return $localForage.getItem('clientId').then(function(clienId) {
                                        loginService.setClientId(clienId);

                                        return $localForage.getItem('email').then(function(email) {
                                            loginService.setEmail(email);
                                        })
                                    })
                                })
                            })
                        })
                    }
                }
            })

            .state('login', {
                url: "/login",
                cache: false,
                templateUrl: "templates/login.html"
                //controller: "LoginCtrl"
            })

            .state('tab', {
                url: '/tab',
                cache: false,
                abstract: 'true',
                templateUrl: 'templates/tabs.html'
            })

            .state('tab.images', {
                url: '/images',
                cache: false,
                views: {
                    'tab-images': {
                        templateUrl: 'templates/tab-images.html',
                        controller: 'ImagesCtrl'
                    }
                }
            })

            .state('tab.videos', {
                url: '/videos',
                cache: false,
                views: {
                    'tab-videos' : {
                        templateUrl: 'templates/tab-videos.html',
                        controller: 'VideosCtrl',
                        resolve: {
                            /*mediaServer: function(MediaServerService) {
                             return MediaServerService.startServer().then(function(url) {
                             return url;
                             });
                             }*/
                            mediaServer: function(MediaServerService) {
                                MediaServerService.updateStatus().then(function(url) {
                                    return MediaServerService.stopServer();
                                }, function(error) {
                                    //
                                })
                            }
                        }
                    }
                }
            })

            .state('tab.texts', {
                url: '/texts',
                cache: false,
                views: {
                    'tab-texts': {
                        templateUrl: 'templates/tab-texts.html',
                        controller: 'TextsCtrl'
                    }
                }
            })

            .state('edit', {
                url: '/edit',
                abstract: true,
                cache: false,
                controller: 'EditCtrl',
                templateUrl: 'templates/edit.html'
            })

            .state('edit.image', {
                url: ('/image'),
                cache: false,
                views: {
                    'edit-image': {
                        templateUrl: 'templates/edit-image.html',
                        controller: 'MediaCtrl'
                    }
                },
                data: {
                    type: 'image'
                }
            })

            .state('edit.video', {
                url: ('/video'),
                cache: false,
                views: {
                    'edit-video': {
                        templateUrl: 'templates/edit-video.html',
                        controller: 'MediaCtrl'
                    }
                },
                data: {
                    type: 'video'
                }/*, resolve: {
                 media: function(MediaFileFactory, loginService, MediaService) {
                 return MediaFileFactory.auth(loginService.getToken()).query({media_id: MediaService.getCurrentMediaId()}).$promise;
                 }
                 }*/
            })

            .state('edit-product', {
                url: ('/product'),
                cache: false,
                templateUrl: 'templates/edit-product.html',
                controller: 'ProductCtrl'
            })

            .state('view', {
                url: '/view',
                abstract: true,
                cache: false,
                controller: 'ViewCtrl',
                templateUrl: 'templates/view.html',
                data: {
                    type: ''
                }
            })

            .state('view.image', {
                url: ('/image'),
                cache: false,
                views: {
                    'view-image': {
                        templateUrl: 'templates/view-image.html',
                        controller: 'MediaCtrl'
                    }
                },data: {
                    type: 'image'
                }
            })

            .state('view.video', {
                url: ('/video'),
                cache: false,
                views: {
                    'view-image': {
                        templateUrl: 'templates/view-video.html',
                        controller: 'MediaCtrl'
                    }
                },data: {
                    type: 'video'
                }
            })

            .state('stages', {
                url: '/stages',
                cache: false,
                templateUrl: 'templates/stages.html',
                controller: 'StagesCtrl'
            })

            .state('offline', {
                url: '/offline',
                templateUrl: 'templates/offline.html',
                controller: 'OfflineCtrl'
            })

            .state('camera', {
                url: '/camera',
                cache: false,
                templateUrl: 'templates/camera.html',
                controller: 'CameraCtrl',
                data: {
                    type: 'image'
                }
            })

            .state('videocamera', {
                url: '/videocamera',
                cache: false,
                templateUrl: 'templates/videocamera.html',
                controller: 'VideoCameraCtrl',
                resolve: {
                    mediaServer: function(MediaServerService) {
                        return MediaServerService.startServer().then(function(url) {
                            return url;
                        });
                    }
                },data: {
                    type: 'video'
                }
            })

            .state('product', {
                url: '/product',
                cache: false,
                templateUrl: 'templates/product.html',
                controller: 'ProductCtrl'
            });

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

        //Http Provider
        $httpProvider.interceptors.push(function ($q, $rootScope) {
            return {
                request: function (config) {
                    $rootScope.$broadcast('loading:show');

                    return config;
                },
                response: function (response) {
                    $rootScope.$broadcast('loading:hide');

                    return response;
                },
                requestError: function (rejection) {
                    console.log(rejection.status);

                    $rootScope.$broadcast('loading:hide');

                    return $q.reject(rejection);
                },
                responseError: function (rejection) {
                    console.log(rejection.status);

                    $rootScope.$broadcast('loading:hide');
                    /*if (rejection.status === 401) {
                     $rootScope.$broadcast('401');
                     } else if(rejection.status == 500) {
                     $rootScope.$broadcast('500');
                     }*/

                    return $q.reject(rejection);
                }
            }
        });

        $httpProvider.defaults.useXDomain = true;
        //$httpProvider.defaults.withCredentials = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
        $httpProvider.defaults.headers.common["Accept"] = "application/json";
        $httpProvider.defaults.headers.common["Content-Type"] = "application/json";
        $httpProvider.defaults.headers.common["Content-Type"] = "application/json";

        $sceDelegateProvider.resourceUrlWhitelist(['**']);
    });

The controller:

.controller('LoginCtrl', function ($scope, $ionicPopup, loginService, $state, LoginFactory, $localForage) {

        function login(loginForm) {
            console.log("CICCIO: FORM");
            if (loginForm.$valid) {
                console.log("CICCIO :VALIDA");
                if (!loginService.isLogged()) {
                    $localForage.setItem('email', $scope.email).then(function() {
                        loginService.setEmail($scope.email);
                    });

                    var loginQueryString = "username=" + $scope.email +
                        "&client_secret=" + loginService.getClientSecret() +
                        "&grant_type=password&client_id=" + loginService.getClientId() +
                        "&password=" + $scope.pass;

                    console.log("CICCIO :STOP PER");

                    LoginFactory.login({}, loginQueryString, function(data) {
                        console.log("CICCIO: ECCHE " + data);

                        var token = data.access_token;
                        var refreshToken = data.refresh_token;

                        if (token != null) {
                            $localForage.setItem('token', token).then(function() {
                                loginService.setToken(token);

                                $localForage.setItem('refreshToken', refreshToken).then(function() {
                                    loginService.setRefreshToken(refreshToken);

                                    $state.go('home');
                                });
                            });
                        } else {
                            loginForm.email.$touched = false;
                            loginForm.pass.$touched = false;

                            $ionicPopup.alert({
                                title: 'Errore',
                                template: '<div class="alert">Dati non corretti o problema alla rete, riprovare.</div>',
                                okText: 'Chiudi',
                                okType: 'button button-assertive'
                            });
                        }
                    }, function(data) {
                        console.log("CICCIO: ECCHE ERRORE " + data);
                        loginForm.email.$touched = false;
                        loginForm.pass.$touched = false;

                        $scope.email = '';
                        $scope.pass = '';

                        if(data == null) {
                            $ionicPopup.alert({
                                title: 'Errore',
                                template: '<div class="alert">Problema di rete, riprovare più tardi.</div>',
                                okText: 'Chiudi',
                                okType: 'button button-assertive'
                            });
                        } else {
                            $ionicPopup.alert({
                                title: 'Errore',
                                template: '<div class="alert">Nome utente o password errati, riprovare.</div>',
                                okText: 'Chiudi',
                                okType: 'button button-assertive'
                            });
                        }
                    });

                    console.log("CICCIO :FINITO");
                }
            }
        }

        function logout() {
            loginService.logout();
            $state.go('login');
        }

        $scope.init = function() {
            if(loginService.isLogged()) {
                $state.go('home');
            }
        };

        //$scope.init();

        $scope.login = login;
        $scope.logout = logout;
        $scope.email = '';
        $scope.pass = '';
    })

and using this factory and service:

.factory('LoginFactory', ['$resource', 'AppService', function($resource, AppService) {
        return $resource(AppService.getServerAddress() + "/oauth/access_token", {},
            {
                login: {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    },
                    timeout: 1
                }
            }
        );
    }])
.service('loginService', ["$rootScope", 'LoginFactory', '$localForage', function ($rootScope, LoginFactory, $localForage) {
        var token = null;
        var refreshToken = null;
        var clientSecret = null;
        var clientId = null;
        var email =  null;

        var loginTries = 0;

        this.setToken = function(t) {
            token = t;
        };

        this.setRefreshToken = function(r) {
            refreshToken = r;
        };

        this.setClientSecret = function(s) {
            clientSecret = s;
        };

        this.setClientId = function(i) {
            clientId = i;
        };

        this.setEmail = function(e) {
            email = e;
        };

        this.getToken = function() {
            return token;
        };

        this.getRefreshToken = function() {
            return refreshToken;
        };

        this.getClientSecret = function() {
            return clientSecret;
        };

        this.getClientId = function() {
            return clientId;
        };

        this.getEmail = function() {
            return email;
        };

        this.isLogged = function() {
            if(token == null) {
                return false;
            } else {
                return true;
            }
        };

        this.logout = function() {
            if (this.isLogged()) {
                $localForage.removeItem('token').then(function() {
                    token = null;

                    $rootScope.$broadcast('logout');
                });
            }
        };

        this.refreshToken = function() {
            if(refreshToken != null) {
                var refreshQueryString = "username=" + email +
                    "&client_secret=" + clientSecret +
                    "&grant_type=refresh_token&client_id=" + clientId +
                    "&refresh_token=" + refreshToken;

                LoginFactory.login({}, refreshQueryString, function(data) {
                    var nToken = data.access_token;
                    var rToken = data.refresh_token;

                    if (nToken != null) {
                        $localForage.setItem('token', nToken).then(function(){
                            token = nToken;

                            $localForage.setItem('refreshToken', rToken).then(function() {
                                refreshToken = rToken;
                            })
                        })
                    } else {
                        logout();
                    }
                }, function(data) {
                    $localForage.getItem('loginTries').then(function(loginTries) {
                        if(loginTries < 3) {
                            loginTries = loginTries + 1;
                        } else {
                            loginTries = 0;
                            logout();
                        }
                    })
                });
            }
        };
    }])

Sounds a lot like a CORS problem. Explanations:

https://blog.nraboy.com/2015/05/whitelist-external-resources-for-use-in-ionic-framework/
Making REST call from Ionic

Make sure you’ve done the following;

In your index.html, have a Content-Security-Policy tag, e.g:

<meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src  'self' 'unsafe-inline' *">

Make sure you’ve installed the Cordova Whitelist plugin, so your package.json should look like:

 "cordovaPlugins": [
...
    "cordova-plugin-whitelist",
...

And in your config.xml you would have:

  <access origin="*"/>

Not sure if ALL of these are necessary, and probably some of the above settings are too “wide” and you can tighten them to improve security. But you can start tweaking that after you’ve got your stuff working.

Posted my source in the first post, I’ve already had all these plugins, settings and tags in my code. Works on emulators and browser (even on And

Solved, I was miss-configuring the CSP meta tag, wrong use of wildcards, correct tag:

<meta http-equiv="Content-Security-Policy" content="default-src *; connect-src http://localhost:* ws: blob:
    http://192.168.2.2:* file:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">

Hey how did you find out what url to use for your blob?