Accueil Nos publications Blog Allez plus loin avec Windows Azure Mobile Services

Allez plus loin avec Windows Azure Mobile Services

windowsazure_logo-300x44J’ai présenté dans différents articles de blog Windows Azure Mobile Services, avant tout lors de sa sortie, puis après la première mise à jour importante de ce service. Cependant, nous n’avons qu’exploré la surface des possibilités, et il est possible d’aller beaucoup plus loin avec ce service. C’est dans le cadre d’une préparation d’une soirée très très technique pour Soat, ou plus communément appelée une soirée 3T, avec David Poulin, nous avons décidé de relever un petit challenge. En soit, cela consiste à créer une application où l’on peut se connecter avec son compte Facebook, afin de voir son profil et sa liste d’amis comme donnée de base. Nous allons voir étape par étape comment nous sommes arrivés au résultat escompté.

Etape 1 : Créer notre service sur Windows Azure Mobile Services.

Je l’ai déjà présenté au sein des articles précédents, et cela a très peu changé, il faut vous rendre sur le portail Azure et créer un nouveau service de type Windows Azure Mobile Services comme celui-ci :

Capture

Après la création de celui-ci, il est possible d’accéder au tableau de bord de ce service, ou vous retrouverez des exemples d’utilisation de Windows Azure Mobile Services, à noter qu’il y a maintenant la possibilité de créer des applications pour Android et HTML5 / JavaScript. Cette technologie est donc maintenant disponible pour toutes les plateformes mobiles, elle peut donc facilement être utilisée pour créer un backend commun entre plusieurs plateformes.

Maintenant que nous avons créé notre service, nous allons gérer les identifiants de notre application Facebook.

Etape 2 : Créer son application au sein de Facebook

Il vous faut avant tout un compte Facebook, puis après vous allez dans la partie réservée aux développeurs d’application via cette url : https://developers.facebook.com/apps puis après vous pouvez créer une application, comme ci-dessous :

Capture

Il faut ensuite le configurer, comme cela, afin que la partie de login utilise l’url de base de notre Windows Azure Mobile Services.

Capture

Tout est fin prêt, il est maintenant possible de renseigner ces identifiants dans la partie Identité sur le portail Azure.

Etape 3 : Créer son application Windows Phone 8.0

Nous allons donc partir d’une application vierge, et nous y allons ajouter un package NuGet qui est celui-ci WindowsAzure.MobileServices

CaptureA noter, qu’il est aussi possible de prendre la version 0.3.1 qui est en pré-release actuellement, et qui contient un certain nombre de modification par rapport à la précédente, mais qui a l’avantage d’être une portable Library, et donc de pouvoir marcher sur Windows Phone 7 / 7.5.

Après le système d’authentification que je ne détaillerai pas dans cet article, il est possible d’accéder au UserId de notre utilisateur connecté, par exemple dans mon cas nous aurions ceci :

Capture

Et bien entendu, cet id facebook ne parle à personne, même à moi qui ne l’ai absolument pas appris par coeur…

Ce que nous avons décidé de faire, c’est lors de la connexion de l’utilisateur, de lui créer un compte dans notre système au sein de notre backend. Pour cela, je vais créer une table “users” avec ces permissions :

Capture

Donc tout ce passe en mode script sauf la lecture des utilisateurs, on va donc créer notre entité au niveau de notre application.


[DataContract(Name="users")]
public class User
{
    [DataMember(Name="id")]
    public long Id { get; set; }

    [DataMember(Name = "userid")]
    public string UserId { get; set; }

    [DataMember(Name = "username")]
    public string UserName { get; set; }

    [DataMember(Name = "pictureurl")]
    public string PictureUrl { get; set; }

    [DataMember(Name = "token")]
    public string Token { get; set; }
}

Et, nous allons maintenant récupérer nos données depuis la base.


public async Task LoadData()
{
    var user = App.ServiceClient.CurrentUser;
    MeViewModel.UserId = user.UserId;

    var userTable = App.ServiceClient.GetTable<User>();
    var query = userTable.Where(n => n.UserId == user.UserId);
    var result = await userTable.ReadAsync<User>(query);
    MeViewModel.User = result.FirstOrDefault();
}

Ce que nous faisons, c’est donc lire dans la table Users la ligne qui contient mon utilisateur. Et maintenant tout va se passer au niveau du backend Mobile Services.

Etape 4 : Au niveau du backend

Donc au niveau du backend, comme action, nous avons besoin de récupérer les informations de notre utilisateur sur Facebook, que ce soit son nom, sa photo de profile, son token si l’on souhaite réaliser une connection automatique au lancement de l’application, et son Id Facebook qui est unique et qui permet d’accéder à diverses infos sur le site comme construire l’url du profil. Je vais donc vous montrer comment l’on fait cela par étape, afin de ne pas vous fournir 100 lignes de code sans explication….


function read(query, user, request) {
    request.execute({
        success: function (results) {
            if (results.length === 0) {
                getAndInsertInformations(user, request, function(result) {
                    var items = [];
                    items.push({
                        userid: user.userId,
                        username: result.username,
                        pictureurl: result.pictureurl,
                        token: result.token
                    });
                    
                    console.log(result);
                    request.respond(statusCodes.OK, items);
                });
            } else {
                request.respond(statusCodes.OK, results);
            }
        },
        error: function () {
            request.respond(statusCodes.INTERNAL_SERVER_ERROR);
        }
    });
}

Alors dans le bout de node.js que vous pouvez voir ci-dessus, je vais exécuter ma fonction read, qui va chercher en base si j’ai un utilisateur, et si ce n’est pas le cas je vais appeler ma fonction getAndInsertInformations et renvoyer les données à mon application. A noter qu’il ne faut pas oublier d’effectuer un request.respond(), sinon votre application attend un retour jusqu’au timeout qui vous déclenchera une erreur.

Maintenant, voyons le contenu de la méthode getAndInsertInformations :


function getAndInsertInformations(user, request, callback) {
    var identities = user.getIdentities();
    var req = require('request');
    
    if (identities.facebook) {
        var fbAccessToken = identities.facebook.accessToken;
        console.log(fbAccessToken);
        var urlProfile = 'https://graph.facebook.com/me?access_token=' + fbAccessToken;
        
        req(urlProfile, function(err, resp, body){
            if (err || resp.statusCode !== 200) {
                console.error('1 - Error sending data to FB graph API : ', err);
                request.respond(statusCodes.INTERNAL_SERVER_ERROR, body);
            } else {
                var userProfileData = JSON.parse(body);
                
                var urlPicture = 'https://graph.facebook.com/' + userProfileData.id + '/picture?access_token=' + fbAccessToken;

                var result = {
                    username: userProfileData.username,
                    token: fbAccessToken,
                    pictureurl: urlPicture,
                    userid: user.userId
                };
                
                tables.getTable('users').insert(result);
                
                callback(result);
            }
        });
        
    }
}

On commence déjà par récupérer notre token Facebook, puis après on va utiliser le graph api de Facebook pour récupérer les informations qui nous intéressent, c’est à dire le nom, prénom et son image de profil.

Après avoir récupéré nos informations depuis Facebook, nous pouvons directement les enregistrer en base, tout en prenant soin de les renvoyer. Ainsi, nous n’aurons plus besoin d’appeler Facebook pour les appels ultérieurs. Au niveau de l’identification, il est possible de s’en affranchir en gardant le user id généré par mobile services au niveau de l’application.

Etape 5 : Le scheduler

Donc récupérer les informations sur son compte, c’est bien intéressant, mais généralement on sait comment on se nomme Et on se reconnait sur notre photo de profil Facebook :-). Donc je propose de récupérer la liste de tous ses amis.

Pour cela, je vais créer un scheduler qui va tourner tous les jours, afin de récupérer les amis de  mes différents utilisateurs.

Capture

Et après, dans la partie script il n’y a plus qu’à ajouter mon script qui va parcourir ma liste d’amis sur Facebook et les ajouter dans une table ‘friends’.


function importfriends() {
    
    tables.getTable('users').read({
            success: function(results) {
                for (var i = 0; i < results.length; i++) {
                    var currentUser = results[i];
                    var fbToken = currentUser.token;
                    
                    var req = require('request');
                    var urlFriends = 'https://graph.facebook.com/me/friends?access_token=' + fbToken;
                    
                    req(urlFriends, function (err, resp, body){
                        if (err || resp.statusCode !== 200) {
                            console.error('Error sending data to FB graph ' + err);
                        } else {
                            var friendsData = JSON.parse(body);
                            console.log(friendsData);
                            
                            var countsuccess = 0;
                            var counterror = 0;
                            var countignore = 0;
                            
                            var j = 0; 
                            var insertNext = function() {
                                if (j < friendsData.data.length) {
                                    var currentFriend = friendsData.data[j];
                                    var item = {
                                        friendid: currentUser.userid, 
                                        name: currentFriend.name,
                                        facebookid: currentFriend.id,
                                        picture: 'https://graph.facebook.com/' + currentFriend.id + '/picture?access_token=' + fbToken
                                    };
                                    
                                    tables.getTable('friends')
                                        .where({ facebookid: currentFriend.id })
                                        .read({
                                                success: function(results) {
                                                    if (results.length > 0) {
                                                        countignore++;
                                                        j++;
                                                        insertNext();
                                                    } else {
                                                        tables.getTable('friends').insert(item, { 
                                                            success: function() {
                                                                j++;
                                                                countsuccess++;
                                                                insertNext(); 
                                                            },
                                                            error: function() {
                                                                counterror++;
                                                            }
                                                        });
                                                    }
                                                }
                                          });
                                }
                                else {
                                    console.log('Success : ' + countsuccess + ' Error : ' + counterror + ' Ignore : ' + countignore);
                                }
                            }
                            
                            insertNext();
                        }
                    });
                }
            }
        });
}

Bon vu comme cela, ça peut paraître un peu “barbare”, mais cela me permet de récupérer tous mes amis Facebook et de les ajouter dans ma base de données.
Ainsi, je peux “les utiliser” comme source de données pour mes applications Windows 8, Windows Phone 8, Android, iOS, HTML/JS, Windows Phone 7.

Pour conclure

Et voilà, ce cas d’utilisation tombe bien, car je voulais vous montrer qu’il est possible de faire des choses un peu plus complexe rien qu’au niveau du serveur Mobile Services, et donc garder une vraie logique business au niveau du backend, et ne pas tout écrire au niveau de vos applications mobiles. Ainsi, il devient plus simple de réaliser des applications sur plusieurs devices sans avoir à réimplémenter toute votre couche business.