Tutoriel “Développer nativement pour iOS et Android en C# & .NET avec Xamarin” (partie 1)

 

Avec plus d’un milliard de téléphones portables expédiés à travers le monde en 2013, comme le montrent les chiffres donnés par l’IDC, les applications mobiles ont un bel avenir devant elles. Les 3 plateformes qui se partagent le marché au dernier trimestre 2013 ne sont autres qu’Android, iOS et Windows Phone. Microsoft est toujours très loin en troisième position. Mais il affiche une progression de 46,7% entre les quatrièmes trimestres 2012 et 2013. Alors que les deux Leaders affichent des évolutions de 40,3% pour Google et 6,7% pour Apple. Pour une entreprise (ou un développeur) de culture .NET qui souhaite apparaître sur ces 3 plateformes, un outil permet de développer nativement sur iOS et Android en C# : Xamarin. Fondé en 2011, Xamarin tire ses racines du projet Open Source Mono qui avait pour but de développer une plateforme .NET sur Linux. Bien évidemment, l’idéal serait de développer directement en Java sur Androïd et en Objective-C sur iOS. Mais les besoins en termes de minimisation des coûts combinés à la meilleure expérience utilisateur possible peuvent s’avérer importants. C’est en cela que Xamarin peut être une bonne solution.

Xamarin propose gratuitement un IDE intitulé Xamarin Studio à condition que la taille du code compilé (IL) de l’application soit inférieure à 64k. Sinon il faudra débourser la somme de 299$. Pour ceux qui souhaitent développer sous Visual Studio et profiter de tous ses avantages, Xamarin a développé un plugin à 999$. Pas très accessible pour les développeurs particuliers donc, surtout qu’il ne marche pas sur la version Express de Visual Studio. Mais plutôt intéressant dans le cadre d’une entreprise. A noter qu’il vous faudra un Mac pour développer votre application iOS sous Xamarin Studio, alors que ce n’est pas nécessaire si vous passez par le plugin. En effet celui-ci utilise une machine virtuelle pour la compiltation.

EDIT 04/02/2015 : Si vous passez par le plugin Xamarin pour Visual Studio, il vous suffira d’être connecté en réseau à un MAC.

 Le site de Xamarin propose une bonne documentation et des exemples  intéressants d’applications. Pour un développement multi-plateformes, l’architecture préconisée est la suivante :

clip_image001

  • Une couche commune “Core” séparée en plusieurs couches (layers) classiques. Elle composée de la Data Layer, Data Access Layer, Service Access Layer et de la Business Layer. Elle utilise les librairies communes aux 3 plates-formes;
  • Pour chaque plateforme, une couche “App Layer” (code spécifique à la plate-forme) et une couche “User Interface”.

Shake 8

Vous trouverez sous la forme de tutoriels notre premier développement sous Xamarin Studio : Shake8. Inspirée de la “Magic 8 ball” (la boule de billard n°8 qui répond à n’importe quelle question), Shake8 est une application qui permet de customiser ses propres “8 ball”. L’utilisateur choisit pour chaque boule les différentes possibilités de réponse. Il lui suffit ensuite de secouer son téléphone et Shake8 fait un choix.

Voici les différentes fonctionnalités proposées par Shake8 :

  • Visualisation de la liste de “balls” ;
  • Possibilité de créer, effacer et éditer une “ball”;
  • Voir la liste des choix pour la “ball” séléctionnée;
  • Possibilité de créer des choix pour une “ball”;
  • S’il y a au moins 2 choix pour une “ball”, lorsqu’on sélectionne celle-ci, il suffit de secouer le téléphone pour que Shake8 fasse un choix;
  • Faire apparaître le résultat d’une secousse de Shake8 dans la liste de “balls”.

Nous avons développé la partie Android et iOS sous Xamarin Studio. Le tutoriel sera fourni sur ce blog en 2 parties comme suit :

Le code source est disponible ici.

I/ Développer une couche cross plateformes iOS / Android / Windows Phone

Pour ce tutoriel, vous aurez besoin d’installer Xamarin Studio. La couche CrossPlateform est commune aux 3 plateformes. Elle ne peut contenir que les frameworks communs, comme System, System.Core et System.Xml. Pour notre application Shake8, ouvrez Xamarin Studio et créez une nouvelle solution. Sélectionnez « Bibliothèque », puis renseignez le nom du projet et le celui de la solution.

clip_image003

Organisez le projet en ajoutant les 3 couches que nous allons utiliser :

  • Data
  • DataAccess
  • Business.

clip_image004

A/ Créez des classes de stockage de données

clip_image005

La couche Data permet le stockage physique des données, qu’il soit sous forme de base de données, fichier plat ou autre. Dans le cas de Shake8 nous utilisons SQLite.

B/ Fichier SQLite.cs

SQLite est embarqué dans les OS de iOS et Android mais pas dans celui du Windows Phone. Afin de pouvoir partager le code à toutes les plateformes, une version native de SQLite pour Windows Phone est nécessaire. Dans Shake8, cela se fait via l’utilisation du code open source de C# SQLite. Ce code correspond à ce qui est fait sur les autres plateformes. Ce sont les options de compilation dans le projet Windows Phone qui permettront d’assurer la bonne utilisation de la librairie.

clip_image007

 Nous allons ajouter ces classes de données aux projets :

clip_image008

Ball et Choice représentent respectivement une “ball” et un choix d’une “ball”. Notez que nous n’avons pas mis en propriété une liste de Choice dans la classe Ball car SQLite ne supporte pas les objets d’objets. C’est pour cela que chaque Choice possède une propriété BallID qui permet de connaître à quelle Ball elle appartient. Ces classes héritent de la classe abstraite EntityBase qui implémente l’interface IEntity. L’interface IEntity expose juste une propriété ID de type Integer qui représente la clé primaire de l’entité dans la base de données. Ajoutez les classes suivantes au projet:

clip_image009

C/ Fichier IEntity.cs

using System;
namespace Shake8.CrossPlatform.Business.IEntity
{
    public interface IEntity
    {
        int ID { get; set; }
    }
}

Cette interface est créée pour que n’importe quelle classe qui l’implémente puisse persister dans la couche Data. Nous allons un peu plus loin créer la classe BallDatabase qui est spécifique à Shake8.

D/ Fichier EntityBase.cs

using System;
using Shake8.CrossPlatform.DataLayer;
namespace Shake8.CrossPlatform.Entity {
/// 
/// Business entity base class. Provides the ID property.
/// 
public abstract class EntityBase : IEntity {
public EntityBase ()
        {
        }
/// 
/// Gets or sets the Database ID.
/// 
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
    }
}

 

On spécifie que la propriété ID est une clé primaire auto incrémentable. Les attributs PrimaryKey et AutoIncrement sont implémentée dans le fichier SQLite.cs.

E/ Fichier BallDatabase.cs

La classe BallDatabase est construite sur SQLite.Net et représente une base de données spécifique, ce qui est dans notre cas celle d’une “ball” de Shake8. Elle contient toutes les méthodes génériques nécessaires pour la persistance des données. Voici un exemple de méthode générique qui utilise l’interface IEntity :

public IEnumerable GetItems () where T : IEntity, new ()
        {
            lock (locker) {
                return (from i in Table () select i).ToList ();
            }
        }

Pour prévenir des accès concurrentiels qui pourraient prévenir de différents threads, on implémente un lock.

F/ Créer l’accès à la base de données

BallRepository

La classe BallRepository encapsule le mécanisme de stockage des données dans une API fortement typée. Elle expose les méthodes du CRUD et utilise les directives de compilation. Il y a en effet parfois quelques divergences sur le chemin où se trouve SQLite en fonction de la plateforme. Voici un exemple de code utilisant les directives de compilation en fonction de la plateforme :

public static string DatabaseFilePath {
            get {
                var sqliteFilename = "BallDB.db3";

#if NETFX_CORE
                var path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, sqliteFilename);
#else

#if SILVERLIGHT
                // Windows Phone expects a local path, not absolute
                var path = sqliteFilename;
#else

#if __ANDROID__
                // Just use whatever directory SpecialFolder.Personal returns
                string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
                // we need to put in /Library/ on iOS5.1 to meet Apple's iCloud terms
                // (they don't want non-user-generated data in Documents)
                string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
                string libraryPath = Path.Combine (documentsPath, "../Library/"); // Library folder
#endif
                var path = Path.Combine (libraryPath, sqliteFilename);
#endif

#endif
                return path;
            }
        }

 

Le développement de la couche cross plateforme est désormais terminé. Notez qu’il existe des limitations d’utilisation de certaines fonctionnalités du langage C# sur les plateformes iOS et Androïd.

G/ Limitations sur iOS

  • Les classes génériques ne peuvent hériter de NSObjects. Par exemple, le code suivant n’est pas supporté pas car UIView hérite de NSObject :
class MyGenericView : UIView {
  [..]
}

Mais à partir de la version 7.2.1 de Xamarin.iOS, actuellement en version alpha, il sera possible de le faire dans certains cas.

  • P/Invokes n’est pas supporté sur les classes génériques;

Le code suivant ne fonctionne pas :

class GenericType {
    [DllImport ("System")]
    public static extern int getpid ();
}
  • L’utilisation de Property.SetInfo sur les types Nullable pour lui affecter une valeur n’est pas supporté;
  • On ne peut utiliser le type Dictionary<TKey, TValue>. En effet le constructeur par défaut utilise EqualityComparer.Default qui fait appel à Property.SetInfo. Il faut donc implémenter manuellement l’interface IEqulityComparer. Vous trouverez un exemple d’implémentation concrète ici.

Pas de génération de code dynamique car le noyau de l’iPhone ne le permet pas. Ce qui signifie que :

  • System.Reflection.Emit n’est pas supporté;
  • System.Runtime.Remoting non plus.

Il n’est pas possible de créer des types dynamiquement (en utilisant Type.GetType);

  • Remoting n’est pas supporté.

H/ Limitation sur Android

  • Pour les classes dérivées, il n’est pas possible d’implémenter un constructeur qui n’existe pas dans la classe mère. Par exemple, le code suivant ne fonctionne pas :
[Service]
class MyIntentService : IntentService {
    public MyIntentService ()
        : base ("value")
    {
    }
}

Cependant, il est possible de faire ceci si vous souhaitez contourner le problème :

[Service]
class MyIntentService : IntentService {
    [Obsolete ("DO NOT USE", true)]
    public MyIntentService ()
    {
    }

    // ...
}
  • [Export] et [ExportField] ne sont pas supportés sur les classes génériques. Les codes suivants ne fonctionnent pas :
public class Example : Java.Lang.Object {

    // Invalid; generates XA4207
    [Export]
    public static void Method(T value)
    {
        ...
    }
}
public abstract class Parcelable : Java.Lang.Object, IParcelable {

    // Invalid; generates XA4207
    [ExportField ("CREATOR")]
    public static IParcelableCreator CreateCreator ()
    {
        ...
    }
}

Ressources 

Le code source est disponible ici.

La prochaine étape sera de développer la partie spécifique à Android.

Rendez-vous ici pour la partie 2 du tutoriel !

 

Share
Cécile BOUNSINH
Cécile BOUNSINH

30336

Comments

  1. Bonjour,
    tutoriel très intéressant !
    Dans votre description de Xamarin, vous parlez d’un plugin qui utilise une machine virtuelle pour la compilation sans utiliser de mac.
    Pouvez vous me donner un lien vers ce plugin ?
    merci

  2. Cécile Bounsinh Cécile Bounsinh Says: February 4, 2015 at 4:36 pm

    Bonjour,
    Merci pour votre commentaire =). Car du coup je me suis remise à étudier Xamarin pour préparer la partie 3 du tutoriel (mais je pars très loin et longtemps donc vous verrez le bout de son nez en avril 2015).
    Au début de l’article, je parle du plugin Xamarin pour visual studio.
    En réalité vous avez quand même besoin d’un MAC! Il faut qu’il soit connecté en réseau avec votre PC.
    Un tutoriel en anglais est dispo ici si vous souhaitez savoir comment faire : http://developer.xamarin.com/guides/ios/getting_started/installation/windows/introduction_to_xamarin_ios_for_visual_studio/

  3. Bonjour,

    Merci pour ce riche tutoriel sur une techno très promettant et sur laquelle beaucoup de gens sont en quête de formations.
    Pour ce qui me concerne, j’ai été enthousiasmé par Xamarin mais vite dissuadé d’aller plus loin par le coût de licence que j’ai trouvé excessif, surtout pour une techno nouvelle. Ça a peut-être changé depuis.

    Cordialement.

  4. je suis un débutant je voudrais faire une petit application pour ajouter,modifier,supprimer,afficher,rechercher des donne dans une base de donnée si possible de m’aider et merci

  5. Merci Madame

Leave a Reply

Your email address will not be published. Required fields are marked *