Écriture/lecture/modification de fichiers dans un projet Universel app/UWP et cordova

Dans nos applications, nous avons pris le parti d’écrire nos fichiers en JSON. Nous avons donc conçu une abstraction (en WinJS, avec un système de promises) qui nous permet d’utiliser des méthodes claires et simples sur toutes les plateformes (WinRT/UWP ou Cordova (iOS/Android) )

Ce module « DataContainer » est disponible dans notre libraire WinJSContrib (Github)

Dans WinJSContrib.DataContainer, nous avons 4 fichiers qui exposent les mêmes méthodes avec des implémentations différentes :

  • read : lecture d’un élément
  • save : enregistrement d’un élément
  • remove : suppression d’un élément
  • list : liste des fichiers d’un container
  • child : création/accès container enfant

Dans une application WinRT/UWP nous allons naturellement utiliser la couche WinRT/UWP pour écrire/lire les fichiers. Pour cela il suffit d’inclure le fichier « winjscontrib.datacontainer.winrt.file.js »

Dans une application cordova IOS ou Android, nous avons plusieurs choix :

  • Utiliser une base de données : winjscontrib.datacontainer.cordova.database.js
  • Utiliser le système de fichiers avec le plugin file : « winjscontrib.datacontainer.cordova.file.js »
  • Utiliser le localStorage : « winjscontrib.datacontainer.localstorage.js » (utilisable en WinRT aussi)

Ensuite, il faut instancier un container parent et l’utiliser partout dans l’application.

Dans le JS des applications Windows 8/Phone il suffit d’instancier le container (dossier) parent :

MyApp.Data.container = new WinJSContrib.DataContainer.WinRTFilesContainer(undefined, { logger: WinJSContrib.Logger });

Et changer WinRTFilesContainer par notre choix (CordovaDatabaseContainer par exemple) pour l’application cordova en faisant attention de ne l’appeler qu’après l’enclenchement de l’évènement deviceready.

Et c’est tout, la magie s’opère à l’intérieur de notre librairie 🙂

Quelques exemples d’utilisation :

  • Pour lire un fichier :
  • Data.container.read("objKey").then(function (data) { }, function (error) { });
    
  • Supprimer un fichier :
  • Data.container.remove("objKey").then(function () { }, function (error) { });
    
  • Enregistrer un fichier :
  • Data.container.save("objKey",obj).then(function () { }, function (error) { });
    
  • Accès à un container enfant (sous dossier) avec la lecture d’un fichier fichier :
  • Data.container.child(folderid).read("subObjKey").then( function (subObjInFolderID) { }, function (error) { }));
    
  • Liste des fichiers dans un container :
  • Data.container.list().then(function (res) {}, function (error) { });
    

Resolving WinJS webcomponents attributes

Now that you know how to use WinJS as webcomponents, and how to declare your controls, we will talk about the mecanism for resolving attribute values.

Lets work with an example :

<win-listview id="recentItemsList" member 
	itemdatasource="list:ctrl:recentItemsPromise" 
	itemtemplate="select:#pictureItem" 
	iteminvoked="event:ctrl:recentListItemInvoked"></win-listview>

You could think of attribute resolution as

[what to do]:[where to look]:[string token]

If you look at the « itemdatasource » attribute, you could read it like this : get the « recentItemsPromise » property from parent control, and wrap it in a WinJS.Binding.List for the ListView.

In this example, « recentItemsPromise » is just a string, and « ctrl » and « list » are operators. The list operator is smart enougth to see that it received a promise, and await it to set value.

Operators are just functions referenced in the namespace WinJSContrib.Utils.ValueParsers. You could provide your own operators by adding them to this namespace.

When the attribute is resolved, you will endup with something equivalent to :

list(domelement, ctrl(domelement, "recentItemsPromise"));

As you can see, their is no complex parsing involved, it is very efficient, and enforce composition. You have no limit at the number of operators you can chain like this.

You could find the list and details about built-in operators in the API documentation.

How to use WinJS resources with a Cordova App

If you need to use WinJS resources in a cordova app, you have to load them manually and that is very simple !

You only have to read the ‘good’ resjson (the file that matches your language) before you call WinJS.UI.processAll  and set the global « strings » variable.

In our apps we use this method to load resources:

var loadLocalRessources = function (language) {
   language = language || 'en';
    return new WinJS.Promise(function (complete, error) {
        var url = './strings/' + language + '/resources.resjson';
        console.log('trying to load resources from ' + url);

        WinJS.xhr({ url: url }).then(function (res) {
            console.log('resource ok for ' + language);
            try {
                window.strings = JSON.parse(res.responseText);
            } catch (exception) {
                console.error('resource parse error ' + exception.message);
            }
            complete(window.strings);
        }, function (err) {
            console.error('resource load error for ' + language + ' ' + err.statusText);
            if (language != 'en') {
                data.loadLocalRessources('en').then(complete, error);
            }
            else {
                error(err);
            }
        });
    });

}

Débuguer une Universal Windows app et d’une application Cordova dans Visual Studio

Petit rappel : Vu l’architecture du projet (Applications natives en Universal App + application cordova) il faut bien penser à ajouter les fichiers copiés depuis le shared project en as link dans l’application cordova. C’est le seule moyen de débuguer/modifier le bon fichier.

 

Dans les applications universelles aucune configuration spéciale n’est nécessaire, Visual Studio gère parfaitement le debug. Il suffit de lancer l’application en mode debug et avoir accès dès le lancement au dom ainsi qu’aux points d’arrêts. Les choses se compliquent légèrement avec les applications cordova. En effet Visual studio met plusieurs secondes (voir minutes) avant d’attacher correctement et d’une façon stable le debugger. Et si on souhaite débuguer les premières lignes qui s’exécutent lors du lancement de l’application, cela devient rapidement compliqué, voir impossible.

Deux solutions existent :

  • La première (mais qui ne marche que si l’application s’initialise correctement = pas de crash au démarrage) c’est simplement via la console JavaScript de Visual Studio d’appeler la méthode window.location.reload() la page index.html est rechargée = les scripts se ré exécutent et on a donc accès aux debug des premières lignes de code.
  • La deuxième c’est de créer un mode debug avec une étape intermédiaire qui consistera à avoir un fichier index.html qui charge le stricte minimum de fichiers qui contient un lien (button) qui va nous permettre de naviguer vers une deuxième page qui va charger le reste des fichiers. Avec cette formule on s’assure du démarrage de l’application, on peut attendre que le debugger Visual Studio soit correctement attaché pour pourvoir charger les autres fichiers.

 

Le débogage/déploiement sous iOS requière un mac et l’installation des outils de build:

  • (Mac) Depuis le terminal lancer la commande désinstallation: sudo npm install -g vs-mda-remote –user=$USER ($user = l’utilisateur courant)
  • (Mac) Après l’installation lancer la commande: vs-mda-remote –secure false
  • Configurer Visual Sutdio: Tools => Options => Tools for Apache Cordova => remote Agent configuration:
    • Enable remote iOS processing = True
    • Host : adresse ip du mac de build.

Le déploiement peut se faire avec le simulateur ou un device.

Avec ces quelques notes vous avez maintenant les outils pour pourvoir débugger facilement votre nouvelle application.

Universal Windows app et Cordova avec WinJS

L’architecture que je conseil pour cibler les trois (quatres) plateformes, c’est de partir principalement d’un projet natif Universal app (Windows 8.1/ Windows Phone) en HTML5 et de créer un projet Cordova à l’aide du plugin Visual studio.

Ensuite pour brancher l’application Cordova avec le projet shared, il faut écrire un script (robocopy) à exécuter avant le build pour copier les fichiers du projet shared vers le projet cordova:

(robocopy ..\UniversalApp.Shared\ . /E /XF UniversalApp.Shared.*)^& IF %ERRORLEVEL% LEQ 1 exit 0

Et modifier le fichier de projet (jsproj) pour lancer cette exécution:

<Target Name= »BeforeBuild »>
<Message Text= »### BeforeBuild ### » Importance= »high » />
<Exec Command= »prebuild.bat » />
</Target>

Mais pour pouvoir débugguer les fichiers copiers, il faut aussi créer la structure des dossiers et ajouter les fichiers en as link.

Pour ajouter WinJS à vos projets vous pouvez passer par nuget (qui ne marche pas avec les projets shared pour le moment) ou récupérer directement la dernière version stable disponible depuis le repo github. Vous pourrez ensuite ajouter les fichiers WinJS.js, css ui-light.css ou ui-dark .css ainsi que la typo Symbols.ttf dans le dossier scripts du projet shared (cette version de WinJS sera aussi utilisée avec les Universel Apps)

Enfin il reste à inclure les références dans les fichiers default.html et index.html. Votre projet est ainsi prêt et on peut lancer le développement de notre application cross-plateforme.

Note importante: l’initialisation de l’application est différente en WinRT et en Cordova. Sous Windows on va conserver le fichier default.js, et pour le projet Cordova, on va modifier le fichier équivalent, index.js, pour initialiser correctement notre application.

Un exemple de solution est disponible ici

WinJS dans une application cross plateforme Cordova

Depuis avril 2014, WinJS le Framework SPA de Microsoft est devenu libre (disponible sur github) et  surtout cross-platform.
C’est avec ces nouvelles possibilités qu’on peut maintenant l’utiliser sur d’autres plateformes que Windows 8/Phone 8.1.

Dans cette série de posts, je vais donc aborder le développement multiplateforme d’application avec WinJS.

[Build 14] – Strategies for developing Cross-Device applications with Visual Studio 2013

Mail de John
Vendredi 4 avril 2014 06:09

Strategies for developing Cross-Device applications with Visual Studio 2013

 

Retour sur les choix inhérents au développement Cross Platform.

Doit-on choisir le développement natif ou le développement utilisant des technologies web ?
C’est la réponse que cherche à apporter cette session.
Natif : Plus grande flexibilité de customisation par device, accès complet au matériel, device dependant
Web : Device independant, facile à gérer mais possibilités d’intégration à la plateforme limitées.

 

Présentation de stratégies pour le développement web :

– Ne rien faire
– S’adapter au niveau du client
o Duplication minimale mais pas de customisation par device et inefficience au niveau de la bande passante
– S’adapter au niveau du serveur
o Flexibilité maximale mais probablement pas mal de duplication de code
– Tenter d’imiter le fonctionnement natif
o La meilleur expérience sur chaque device mais ce n’est toujours pas du natif

Démonstration sur le CSS et les Media Queries, Bootstrap.
Démonstration JQuery Mobile
Démonstration avec Knockout, TypeScript, Cordova.
Développement natif :

– Utiliser les outils de chaque plateforme
o Impose d’apprendre à développement avec divers IDE, langages
o Pas de partage de code
– Utiliser Xamarin
o Applications complètement native
o Utilisation de Visual Studio
o Partage de la logique du code entre chaque plateforme grâce à des PCL
o 100% des APIs de chaque device sont exposées par Xamarin

Démonstration avec Xamarin et MVVMCross (Breakpoints et remote debug Android)
John