JavaScript
Angular
17 December 2014

Работа с ngCordova в Cordova приложениях

Всем доброго времени суток.

Есть приложение написанное на ionic и использующее Cordova. Суть приложения — выводить некую информацию с сайта.
Ничего сложного нет. Так же, есть зависимость от интернета. Если есть интернет — отображать свежие данные с сайта, если нет — нужно выводить данные «зашитые» в приложение при релизе. Такое уж было пожелание.
Проблемы возникли, когда нужно было определить наличие интернета на устройстве.


Данная статья не является единственным верным решением задачи. Это лишь моя реализация. Найти более грамотное решение мне не удалось. Потому главная задача моего поста, показать, как проблема была реализована мной, и возможно увидеть, почитать замечания\пожелания\советы других людей. Что поможет как и мне лично, так и другим — в решении подобных проблем.

Приложение состоит из главного экрана, и из двух вариантов второстепенных экранов. При смене роута, и загрузки страницы отрабатывает блок resolve, который полностью получает данные, а потом отображает страницу.

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

        $stateProvider.state('main', {
            url: '/',
            templateUrl : "views/main.html",
            controller : "MainController",
            resolve :{
                homepageData : function (appService){
                    return appService.getMainData();
                }
                ...
            }
        });
       
        ...
});


В самом начале, для простоты получения информации о состоянии интернета, я использовал обычную переменную в true | false.

Все работало отлично. И вот финальный аккорд — нужно узнать есть ли интернет на устройстве или нет. Поскольку опыта разработки в данном направлении у меня нет, а сделать нужно! Я начал гуглить. Нашел библиотеку ngCordova — которая реализует взаимосвязь с API Сordova через привычный angular.js. Эта информация(про интернет) мне нужна на этапе обработки роутов. Но куда бы я не пытался вставить этот код — ничего не получалось. Как говорилось: device not ready.

Вот пример одной из попыток.

...
.run(function($ionicPlatform, $rootScope, $cordovaNetwork) {
        $ionicPlatform.ready(function() {
            if(window.cordova && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
            }
            if(window.StatusBar) {
                StatusBar.styleDefault();
            }
            //$rootScope.internetAccess = true;
            $rootScope.internetAccess =  $cordovaNetwork.isOnline();
        });
    });

И как я уже сказал: Error device not ready. Опять в гугл, те решения(для работы с ngCordova) что я находил, были для других плагинов, или не работали вовсе. Попытки сделать на примере других плагинов, ничего не дали.

Решением было дать приложению много обещаний… (: И это сработало. Наобещав золотые горы, оно(приложение) мне поверило и заработало.
Обещания имели вот такой вид:

В resolve:
...
resolve :{
                homepageData : function (appService, $cordovaNetwork){
                    return appService.getMainData().then(function(data){
                        return data;
                    });
                },
                ....
            }
..


и функция в service

         angular.module('myModule').factory('appService', function($q, $http, config_data, $injector, $ionicPlatform) {
    var appData = {
        getMain : function() {

            var defer = $q.defer();
            $ionicPlatform.ready(function(){
                var cordovaNetwork = $injector.get('$cordovaNetwork');
                if(!cordovaNetwork.isOnline()){
                    defer.resolve($http({ method: 'GET', url: config_data.API_HOST + config_data.JSON_PREFIX + 'main.json' }).success(function(data, status, headers, config) {
                        return data;
                    }));
                }else{
                    defer.resolve($http({ method: 'GET', url: 'json/' + config_data.JSON_OFFLINE_PREFIX + 'main.json' }).success(function(data, status, headers, config) {


                        return data;
                    }));
                }
            });

            return defer.promise;
        },
        
    ...
    }
    return appData;
});


Уверен что решение — возможно не самое красивое и правильное, но оно работает. Хочется почитать другие мысли и мнения.

+1
4.6k 30
Comments 1