yeoman

Setup AngularJS & Apache Cordova

Es war doch holpriger als gedacht, aber letztlich funktioniert AngularJS natürlich mit Apache Cordova. Will man auf Systemkomponenten wie GPS, SQLite etc. aus seiner Hybrid App heraus zugreifen, ist es wichtig sicher zu stellen, dass das deviceready-Event seitens Cordova getriggert wurde. Andernfalls funktioniert der Zugriff auf eben beschriebene Komponenten nicht. In einem Standard-Cordova Projekt übernimmt die app.js diese Aufgabe. Im Zusammenspiel mit AngularJS, ist es ein klein wenig tricky.
Ich gehe davon aus, dass NodeJS installiert ist.

Umgebung einrichten

npm install -g yo
npm install -g grunt-cli
npm install -g bower
npm install -g generator-angular
npm install -g cordova

Yo – Yeoman liefert uns an dieser Stelle das Grundgerüst für unsere Hybrid App.
Grunt – Nutzen wir um die Build Tasks anzustoßen und als Webserver. Das Schmankerl an dieser Stelle ist, dass Grunt Änderungen an sämtlichen Files selbst bemerkt und automatisch ein neues Build anstößt. Die Anzeige im Browser wird direkt danach aktualisiert. Kein nerviges F5-Gedrücke mehr. 😀 Der Grunt Server läuft standardmäßig auf Port 9000.
Bower – Dependency Management.
AngularJS Generator – Ein Generator der in Yeoman integriert ist und uns das Erstellen von Angular Komponenten erleichtert.
Cordova – Der Unterbau, der uns den Zugriff auf Systemkomponenten aus AngularJS heraus ermöglicht.

Cordova einrichten

cordova create myapp com.example.myapp MyApp

Über diesen Befehl erstellt Cordova ein neues Projekt. Im angelegten Ordner „myapp“ befindet sich folgende Ordnerstruktur:

myapp
 |___ hooks
 |___ platforms
 |___ plugins
 |___ www

 

AngularJS App erstellen

In der Command Line wechseln wir in den Ordner „myapp“ und erstellen unsere AngularJS App wie folgt:

yo angular

Beim Initialisierungsprozess werden einige Fragen gestellt.  Compass wollen wir nicht nutzen, aber Bootstrap durchaus und die voreingestellten Angular Module auch. Sobald das Build fertig ist, verändert sich die Ordnerstruktur:

myapp
 |___ app
 |___ bower_components
 |___ hooks
 |___ node_modules
 |___ platforms
 |___ plugins
 |___ test
 |___ www

Desweiteren befinden sich jetzt einige .json-Dateien und Gruntfile.js im Ordner. Zuerst editieren wir die Grunfile-JavaScript-Datei.
Dort findet sich rund um Zeile 21 dieser Code:

// Configurable paths for the application
var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
};

dist: ‚dist‘ ändern wir in dist: ‚www‘.
Damit weisen wir Grunt an das künftige Build in den www-Ordner zu schieben, damit wir es später im Cordova Build direkt benutzen können und uns Hin- und Herkopieren sparen.

Grunt schon mal testen

grunt serve

Mit diesem Befehl starten wir den Server. Im Anschluss öffnet sich unser Standardbrowser und wir werden vom Yeoman begrüßt.

Das eigentliche Problem – Cordova deviceready

cordova platform add android

Durch diesen Befehl wird im Ordner „platforms“ der Ordner „android“ angelegt. In diesem befindet sich unter „platform_www“ die cordova.js-Datei. Diese kopieren wir in den „app“ Ordner. Als nächstes editieren wir die index.html im „app“ Ordner. Unter Google Analytics beginnt der Teil, der durch Bower rein kommt. Dazwischen setzen wir…

<script src="cordova.js"></script>

Anschließend erzeugen wir eine AngularJS Factory, damit wir das deviceready-Event abfangen können.

yo angular:factory cordovaready

Yeoman erstellt im „app“ Ordner unter „scripts/services/“ die Factory mit etwas Beispielcode. Diese ändern wir nun etwas ab:

'use strict';

angular.module('myapp')
  .factory('cordovaready', function ($q, $window) {
    var d = $q.defer(),
      resolved = false;

    var self = this;
    this.ready = d.promise;

    document.addEventListener('deviceready', function () {
      resolved = true;
      d.resolve($window.cordova);
    });

// Check to make sure we didn't miss the
// event (just in case)
    setTimeout(function () {
      if (!resolved) {
        if ($window.cordova) d.resolve($window.cordova);
      }
    }, 3000);

// Public API here
    return this;
  });

Das Snippet habe ich selbst auch nur im Internet gefunden siehe https://github.com/perminder-klair/angular-cordova/blob/master/app/scripts/services/cordova.js .

Im Anschluss kann man diese Factory beliebig in Controller injecten zum Beispiel:

angular.module('myappApp')
  .controller('MainCtrl', function ($scope, $http, cordovaready, $cordovaToast) {
    cordovaready.ready.then(function() {
      $cordovaToast.show('Cordova is up!', 'long', 'center')
        .then(function(success) {
          //on success
        }, function(error) {
          //on error
        });
    });
});

Da ich in mir den Zugriff auf Cordova-Komponenten etwas erleichtern wollte, habe ich per Bower noch ngCordova hinzugefügt.

bower install ngCordova

Dadurch weiß ich zum Einen, dass die Factory das erwartete Ergebnis zurückliefert und zum Anderen greife ich schon auf eine Systemkomponenten zu. Hier das Toast.

Build und Deploy

grunt build
cordova build android   // bzw
cordova run android

Abschließend wird über Grunt der Buildprozess angestoßen. Dabei werden sämtliche Dateien minified und in den www-Ordner kopiert. Danach kann entweder das Android Build angestoßen werden oder wenn ein Androidgerät an den PC angeschlossen ist per „run“ direkt auf dem Gerät deployed werden. Für Emulatoren:

cordova emulate android

Resumée

Wichtig ist, die cordova.js-Datei direkt ins app-Verzeichnis zu legen. Nicht unter „scripts“ oder sonst irgendwo hin. Zudem muss die Factory injected werden. Da ein Promise zurück geliefert wird, muss aller folgender Code in der then()-Funktion behandelt werden. Dies gilt jedoch nur, für Cordova Komponenten. Will man im jeweiligen Controller zum Beispiel anderweitig noch Daten an den $scope binden o.ä. geschieht dies außerhalb des then().

Schreib einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *


*