Webservices REST sous Android avec App Engine, Restlet et Objectify

| Nazim Benbourahla | nbenbourahla |

Suite à de nombreuses demandes, ce tutoriel va aborder un sujet important qui est l'interaction entre une application Android et un serveur Google App Engine, en utilisant une communication via Restlet.
Commentez ♪

- Titre : Webservices REST sous Android avec App Engine, Restlet et Objectify

- Auteurs : Nazim Benbourahla, nbenbourahla

- Parution : 21 juin 2011

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2011 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Présentation

- II. Le côté serveur

- II-A. Créer le serveur App Engine

- II-B. Créer l'application web

- II-C. Configurer l'application

- II-D. Création du modèle

- II-E. Création des Webservices Restlet

- III. Le côté client

- III-A. Container

- III-B. EngineConfiguration

- III-C. User

- III-D. UserControllerInterface

- III-E. UserController

- III-F. Création des vues

- III-F-1. Nouvel Utilisateur

- III-F-2. Récupération des utilisateurs

- III-F-3. Autres éléments nécessaires

- III-G. Résultat

- III-H. Conclusion

- III-I. Remerciements

- III-J. Liens

I - Présentation

Notre application permettra d'ajouter et voir des utilisateurs depuis l'interface Android. Voici un ensemble complet des technologies que l'on va utiliser pour ce projet :

- SDK Android ;

- Restlet ;

- Google App Engine ;

- Objectify.

Vous allez comprendre au fur et à mesure l'utilité de chaque technologie dans notre application.
J'ai découpé ce tutoriel en trois parties :

- la création du serveur et sa mise en place ;

- la création des Webservices côté serveur à l'aide de Restlet ;

- l'application Android pour le côté client.

II - Le côté serveur

Tout d'abord nous allons créer notre serveur App Engine. Nous nous occuperons ensuite de l'application web que nous déploierons sur le serveur App Engine. Enfin, nous mettrons en place les Webservices Restlet.

II-A - Créer le serveur App Engine

Pour créer le serveur App Engine, il suffit de vous connecter sur https://appengine.google.com/ à l'aide de votre compte Google. Vous disposez de dix applications gratuites.
Une fois sur l'URL, vous arriverez sur cette page :

Il suffit ensuite de remplir les champs (l'identifiant de l'application est unique donc vous ne pourrez pas utiliser le même que moi pour vos tests !).
Donc pour mon exemple je choisis :

- android-gae-restlet comme identifiant ;

- Tutos Android - Restlet GAE comme nom de l'application ;

- puis cliquez sur Create Application.

Maintenant quand vous retournez sur votre page App Engine, vous verrez ce projet dans la liste et vous pourrez accéder au tableau de bord de votre application ci-dessous :

Voici une explication des plus importants onglets disponibles :

- DashBoard : graphique et statistiques sur l'utilisation des ressources ;

- Logs : équivaut un peu à system.out / err, ce sont les logs de votre application ;

- Datastore Viewer : pour voir le contenu de votre base de données ;

- Application Settings : paramétrage de votre application ;

- Permissions : pour gérer les permissions sur votre application ;

- Version : pour gérer les différentes versions de votre application.

II-B - Créer l'application web

Maintenant vous pouvez ouvrir Eclipse (vous devez auparavant installer les plugins Google (http://code.google.com/intl/fr-FR/eclipse/) et télécharger le SDK App Engine (http://code.google.com/intl/fr-FR/appengine/downloads.html)). Puis, vous serez prêt à commencer. Dans Eclipse, faites un nouveau « Web Application Project », que l'on nommera « GaeAndroidRestlet » avec pour nom de package « com.tuto.android.gae ».
Désélectionnez le SDK GWT et sélectionnez la version du SDK App Engine (1.4.2 dans mon cas). Voici la fenêtre que vous devriez obtenir :

Cliquez ensuite sur Finish et le projet est créé.

II-C - Configurer l'application

Dans le dossier war/WEB-INF de votre projet se trouve un fichier « appengine-web.xml » il faut rajouter l'id de votre application entre la balise <application>, donc dans notre cas.

Maintenant quand vous retournez sur votre page App Engine, vous verrez ce projet dans la liste et vous pourrez accéder au tableau de bord de votre application ci-dessous :

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>android-gae-restlet</application>
<version>1</version>

<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>

</appengine-web-app>

Déployons une première fois pour voir. Il suffit pour cela de cliquer sur l'icône App Engine dans votre Eclipse (icône de moteur d'avion).

Remplissez les données et validez l'opération pour que la phase de déploiement puisse commencer. Un message vous montrera que le déploiement a réussi :

Pour tester, il suffit de vous rendre à l'adresse suivante : iddevotreapplication.appspot.com, donc dans notre cas http://android-gae-restlet.appspot.com/ et vous obtiendrez le résultat suivant :

II-D - Création du modèle

Maintenant que la structure de notre projet est initialisée, créez une classe User qui nous servira à stocker les données en base. Pour indication la base de données de Google App Engine est Big Table, c'est une base NoSql.

Nous allons utiliser Objectify, qui est un framework permettant de simplifier la persistance des données et leur manipulation dans Google App Engine, il rajoute une couche d'abstraction facilitant énormément les différentes interactions.

Nous allons créer notre modèle qui sera stocké en base. Pour cela nous créons un package model dans lequel nous ajoutons une classe User contenant les différents champs.

- Le modèle doit absolument implémenter Serializable.

- Vous devez générer un numéro de serial version.

- Vous devez avoir un champ annoté de @Id qui sera l'id de votre base, (nécessaire pour Objectify).

- Vous devez avoir un constructeur vide.

- Vous devez avoir un getter / setter pour chaque champ.

- Rien de bien compliqué jusqu'à présent.

package com.tuto.android.gae.model;

import java.io.Serializable;

import javax.persistence.Id;

public class User implements Serializable {

private static final long serialVersionUID = 7390103290165670089L;
@Id
private Long id;
private String firstname;
private String lastname;
private String mail;
private String phone;

public User() {

}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public void setMail(String mail) {
this.mail = mail;
}

public String getMail() {
return mail;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getLastname() {
return lastname;
}

public void setLastname(String lastname) {
this.lastname = lastname;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

}

II-E - Création des Webservices Restlet

Nous allons créer nos Webservices Restlet. Pour cela il faut commencer par télécharger les jar de Restlet que je fournis ici et les rajouter à votre projet. Une fois cette étape faite nous allons créer nos webservices.

La première étape pour créer des webservices restlet côté serveur est de modifier le web.xml pour rajouter les lignes suivantes :

<context-param>
<param-name>org.restlet.application</param-name>
<param-value>com.tuto.android.gae.server.RestletDispatch</param-value>
</context-param>

Cette première ligne sert à initialiser restlet et ce qu'on appelle un Dispatcher. Ce dernier recevra les appels Reslet et s'occupera de les rediriger vers la bonne classe pour être traité par le serveur.

Puis nous allons déclarer les Servlets utiles pour nos webservices. On déclare un servlet qu'on nommera RestletServlet et qui correspond à un servlet restlet et on le mappe avec tous les liens qui finissent par /rest/*. Donc tous les liens contenant /rest seront redirigés vers notre RestletDispatch.

<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>
org.restlet.ext.servlet.ServerServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

Voilà la version finale de web.Xml.

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

<context-param>
<param-name>org.restlet.application</param-name>
<param-value>com.tuto.android.gae.server.RestletDispatch</param-value>
</context-param>

<servlet>
<servlet-name>GaeAndroidRestlet</servlet-name>
<servlet-class>com.tuto.android.gae.GaeAndroidRestletServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GaeAndroidRestlet</servlet-name>
<url-pattern>/gaeandroidrestlet</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>
org.restlet.ext.servlet.ServerServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>

Maintenant nous allons créer un package server, dans lequel nous allons créer toutes nos classes indispensables à notre serveur dont notre restlet dispatch qui ressemblera à ceci.

package com.tuto.android.gae.server;

import java.io.File;
import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.LocalReference;
import org.restlet.data.Protocol;
import org.restlet.resource.Directory;
import org.restlet.routing.Router;
import org.restlet.security.Guard;

@SuppressWarnings("deprecation")
public class RestletDispatch extends Application
{
@Override
public synchronized Restlet createInboundRoot()
{
final Router router = new Router(getContext());
router.attach("/user", UserController.class);
return router;
}
}

- Donc un Dispatcher est une classe qui hérite Application et qui implémente la méthode createInboundRoot.

- On crée un nouveau Router avec le context actuel de l'application.

- On indique que les liens contenant /user seront redirigés vers la classe UserController.

- Pas besoin d'indiquer /rest qui est déjà indiqué dans le web.xml.

- Si vous devez passer des arguments à la méthode get, il faut les passer dans l'URL : par exemple /mail/{mail}/pass/{pass} pour passer l'adresse mail et le mot de passe et il suffit de mettre cette valeur à la place de /user dans votre router.attach.

- Pour récupérer ces valeurs passées en paramètre, il suffit d'utiliser :

Request req = super.getRequest();
mail = req.getAttributes().get("mail").toString();

- Vous pouvez avoir plusieurs router.attach.

Pour commencer, nous allons créer un UserControllerInterface, qui sera l'API exposée au client et qui fera le lien entre le client et le serveur.

package com.tuto.android.gae.server;

import org.restlet.resource.Get;
import org.restlet.resource.Put;

import com.tuto.android.gae.model.User;

public interface UserControllerInterface {
@Put
void create(User user);

@Get
Container getAllUsers();

}

Donc on a juste une méthode get et une autre put, rien de bien compliqué. Vous remarquerez la présence d'une classe Container. Pourquoi cette classe, car si jamais vous voulez retourner une List (ArrayList) par exemple, Reslet vous ne retournera pas forcément un ArrayList formaté comme vous le souhaitez donc pour éviter ce problème on crée une classe à nous et on retourne cet objet et comme vous pouvez le voir cette classe contient juste un ArrayList

Ce qui donnera :

package com.tuto.android.gae.server;

import java.util.ArrayList;
import java.util.List;

import com.tuto.android.gae.model.User;

public class Container
{
public List user_list;

public List getUser_list() {
return user_list;
}

public void setUser_list(List user_list) {
this.user_list = user_list;
}

public Container()
{
user_list = new ArrayList();
}

public Container(List user_list)
{
this.user_list = user_list;
}

}

Passons à notre UserController, qui s'occupera de récupérer la liste des utilisateurs ainsi que de stocker les données grâce à objectify dont voici le jar à inclure. (Objectify est un framework utilisé pour faciliter la persistance et la récupération des données depuis un serveur app engine.) Vous pouvez utiliser un autre framework si vous le souhaitez. Cette technologie n'est pas une obligation.

Donc dans notre UserController nous allons implémenter notre create ainsi que notre getAllUser.

- Notre UserController doit absolument hériter ServerResource et implémenter notre interface UserControllerInterface.

- Elle doit posséder un constructeur vide.

- Pour notre create, il suffit d'enregistrer notre modèle et obtenir une instance d'objectify service, puis on crée notre objet user et on le stocke, facile.

- Dans une méthode @Put (donc notre create) on peut passer qu'un seul argument à la méthode Restlet donc.

- Pour notre getAllUser, comme précédemment on fait un register et on récupère une instance (cette partie est obligatoire pour chaque utilisation d'objectify). On récupère tous les utilisateurs à l'aide d'une query (vous pouvez faire des filtres sur la query pour préciser ce que vous souhaitez) puis on crée notre container et on le retourne.

package com.tuto.android.gae.server;

import java.util.ArrayList;
import java.util.List;

import org.restlet.resource.ServerResource;

import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;
import com.tuto.android.gae.model.User;

public class UserController extends ServerResource implements
UserControllerInterface {

public UserController() {
}

@Override
public void create(User user) {
ObjectifyService.register(User.class);
Objectify ofy = ObjectifyService.begin();

User tp = new User();
tp.setFirstname(user.getFirstname());
tp.setLastname(user.getLastname());
tp.setMail(user.getMail());
tp.setPhone(user.getPhone());
ofy.put(tp);
}

@Override
public Container getAllUsers() {
Container content = null;
List users = new ArrayList();
ObjectifyService.register(User.class);
Objectify ofy = ObjectifyService.begin();

Query q = ofy.query(User.class);

for (User u : q)
users.add(u);

content = new Container();
content.setUser_list(users);

return content;
}
}

Voici notre partie serveur terminée, il faut juste la déployer comme expliqué précédemment. Voici le code source du serveur si vous le souhaitez.

III - Le côté client

Nous allons créer un projet Android qu'on nommera GaeAndroidRestletAndroid, avec un SDK 2.1, avec comme nom d'application App Engine Client et comme package com.tuto.android.gae et comme activité de base GaeHomeScreen.
Nous allons ajouter tout d'abord les libs restlet.

Cette application nous permettra soit :

- d'ajouter un utilisateur ;

- récupérer la liste de tous les utilisateurs.

Il faut créer notre première vue qui contient deux boutons (ajout utilisateur et récupération de la liste des utilisateurs).

Donc le fichier XML (main.xml).

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/add_user"
android:id="@+id/addUser"
/>

<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/get_users"
android:id="@+id/getUsers"
/>

</LinearLayout>

Et le fichier Java correspondant.

package com.tuto.android.gae;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class GaeHomeScreen extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button addUser = (Button) findViewById(R.id.addUser);
addUser.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent i = new Intent(GaeHomeScreen.this, AddUserActivity.class);
startActivity(i);
}
});

Button getUsers = (Button) findViewById(R.id.getUsers);
getUsers.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent i = new Intent(GaeHomeScreen.this, GetAllUserActivity.class);
startActivity(i);
}
});

}

}

Il faut créer un package model, dans ce dernier il faut mettre toutes les classes indispensables à la communication restlet.

III-A - Container

- C'est le même que côté serveur.

- Il doit être pareil, car il est utilisé par Restlet pour convertir le JSON reçu depuis le serveur

package com.tuto.android.gae.model;

import java.util.ArrayList;
import java.util.List;

import com.tuto.android.gae.model.User;

public class Container
{
public List user_list;

public List getUser_list() {
return user_list;
}

public void setUser_list(List user_list) {
this.user_list = user_list;
}

public Container()
{
user_list = new ArrayList();
}

public Container(List user_list)
{
this.user_list = user_list;
}

}

III-B - EngineConfiguration

- Cette classe nous sert à configurer notre application pour savoir sur quel serveur elle se connecte.

- Cette classe suit le design pattern singleton.

- On stocke l'adresse vers le lien de notre serveur.

- On instancie un Json converter.

- Vous pouvez reprendre cette classe pour vos autres projets il suffit de changer le gae_path.

package com.tuto.android.gae.model;

import org.restlet.engine.Engine;
import org.restlet.ext.httpclient.HttpClientHelper;
import org.restlet.ext.jackson.JacksonConverter;

public class EngineConfiguration
{
private static EngineConfiguration  ourInstance = new EngineConfiguration();

public final static String  gae_path = "http://android-gae-restlet.appspot.com/";

public static EngineConfiguration getInstance()
{
return ourInstance;
}

public EngineConfiguration()
{
Engine.getInstance().getRegisteredConverters().add(new JacksonConverter());
Engine.getInstance().getRegisteredClients().add(new HttpClientHelper(null));
}

public static EngineConfiguration getOurInstance()
{
return ourInstance;
}

public static void setOurInstance(EngineConfiguration ourInstance)
{
EngineConfiguration.ourInstance = ourInstance;
}
}

III-C - User

- Doit être exactement pareil que côté serveur pour la conversion JSON.

- Il suffit d'enlever l'annotation @id.

- Sinon le reste est pareil.

package com.tuto.android.gae.model;

import java.io.Serializable;

public class User implements Serializable {

private static final long serialVersionUID = 7390103290165670089L;
private Long id;
private String firstname;
private String lastname;
private String mail;
private String phone;

public User() {

}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public void setMail(String mail) {
this.mail = mail;
}

public String getMail() {
return mail;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getLastname() {
return lastname;
}

public void setLastname(String lastname) {
this.lastname = lastname;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

}

III-D - UserControllerInterface

- Même interface que côté serveur.

- De ce fait, les deux parties exposent des méthodes identiques pour la communication entre les deux.

package com.tuto.android.gae.model;

import org.restlet.resource.Get;
import org.restlet.resource.Put;

public interface UserControllerInterface {
@Put
void create(User user);

@Get
Container getAllUsers();
}

III-E - UserController

- C'est la partie importante côté client pour les webserices.

- À la différence du côté serveur, elle ne doit pas implémenter le UserController interface.

- On crée un client ressource dans lequel on instancie le lien vers notre webservice qu'on a défini dans le serveur (cf web.xml et RestletDispatcher).

- On instancie le EngineConfiguration dans le constructeur.

- Il faut toujours faire un wrap de l'interface avant d'appeler la méthode souhaitée.

- Le reste parle de lui-même.

package com.tuto.android.gae.model;

import java.util.List;

import org.restlet.resource.ClientResource;

import android.util.Log;

public class UserController {
public final ClientResource cr = new ClientResource(
EngineConfiguration.gae_path + "/rest/user");

public UserController() {
EngineConfiguration.getInstance();
}

public void create(User user) throws Exception {
final UserControllerInterface uci = cr
.wrap(UserControllerInterface.class);

try {
uci.create(user);
Log.i("UserController", "Creation success !");
} catch (Exception e) {
Log.i("UserController", "Creation failed !");
throw e;
}
}

public List getAllUsers() {
final UserControllerInterface uci = cr
.wrap(UserControllerInterface.class);
Container content = uci.getAllUsers();
return content.getUser_list();
}
}

III-F - Création des vues

III-F-1 - Nouvel Utilisateur

Nous allons commencer par créer la vue pour rajouter un utilisateur (donc fichier XML plus Java).

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" android:hint="Nom" android:id="@+id/userName" />

<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" android:hint="Prenom" android:id="@+id/userFirstName" />

<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" android:hint="Email" android:id="@+id/userMail" />

<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" android:hint="Telephone"
android:id="@+id/userPhone" />

<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Ajouter cet utilisateur"
android:id="@+id/addUserNow" />

</LinearLayout>

Et le fichier Java.

package com.tuto.android.gae;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

import com.tuto.android.gae.model.User;
import com.tuto.android.gae.model.UserController;

public class AddUserActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_user);

Button btn = (Button) findViewById(R.id.addUserNow);
btn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
addUser();
}
});
}

final void addUser()
{
final Thread checkUpdate = new Thread() {
public void run() {
EditText name = (EditText) findViewById(R.id.userName);
EditText firstname = (EditText) findViewById(R.id.userFirstName);
EditText mail = (EditText) findViewById(R.id.userMail);
EditText phone = (EditText) findViewById(R.id.userPhone);
User u = new User();
u.setFirstname(firstname.getText().toString());
u.setLastname(name.getText().toString());
u.setMail(mail.getText().toString());
u.setPhone(phone.getText().toString());
final UserController uc = new UserController();
try {
uc.create(u);
} catch (Exception e) {
return;
}
final Intent intent = new Intent(AddUserActivity.this,
GaeHomeScreen.class);
startActivity(intent);
}
};
checkUpdate.start();
}
}

III-F-2 - Récupération des utilisateurs

Puis on crée la vue de récupération des utilisateurs.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ListView
android:id="@+id/listLists"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10px"/>

</LinearLayout>

Et le fichier Java.

package com.tuto.android.gae;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.tuto.android.gae.model.User;
import com.tuto.android.gae.model.UserController;

public class GetAllUserActivity extends Activity {
private List lists = null;
private List listsName = null;
private ListView listLists;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.get_users);

listLists = (ListView) findViewById(R.id.listLists);

getUsers();

}

final void getUsers() {

UserController list = new UserController();
listsName = new ArrayList();
try {
lists = list.getAllUsers();
} catch (Exception e) {
e.printStackTrace();
}
if (lists != null) {
for (User u : lists) {
if (u != null)
listsName.add(u.getFirstname() + " " + u.getLastname());
}

listLists.setAdapter(new ArrayAdapter(getBaseContext(),
android.R.layout.simple_list_item_1, listsName));

listLists.setTextFilterEnabled(true);

}
}
}

III-F-3 - Autres éléments nécessaires

Sans oublier le strings.xml.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, GaeHomeScreen!</string>
<string name="app_name">App Engine Client</string>
<string name="add_user">Ajouter un utilisateur</string>
<string name="get_users">Voir la liste des utilisateurs</string>
</resources>

Et le AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tuto.android.gae" android:versionCode="1"
android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".GaeHomeScreen" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".AddUserActivity" />
<activity android:name=".GetAllUserActivity" />
</application>

<uses-permission android:name="android.permission.INTERNET" />

</manifest>

Je mets à votre disposition le code de la partie android.

III-G - Résultat

Voici les différents écrans que vous obtiendrez :

- écran d'accueil :

- écran d'ajout d'un utilisateur :

- liste des utilisateurs :

Nous allons tester notre application, pour cela il suffit de la lancer, on va ajouter un nouvel utilisateur.

Maintenant pour vérifier que l'ajout s'est bien passé, on va se connecter à notre compte app engine puis à notre application et on va voir le contenu du DataStore Viewer (ce qui devrait donner) :

On remarque bien qu'un champ en plus est apparu avec l'utilisateur qu'on vient d'ajouter. Dernier test, on va afficher la liste des utilisateurs :

Donc l'utilisateur qu'on vient d'ajouter s'affiche bien dans la liste.

III-H - Conclusion

Voilà c'est ici que s'arrête ce tutoriel, en espérant qu'il vous a aidé à avancer et qu'il a répondu à toutes les questions que vous vous posez. N'hésitez pas à commenter ou à me contacter si une partie ne vous semble pas très claire.

III-I - Remerciements

Je tiens à remercier tout particulièrement Feanorin qui a mis ce tutoriel au format Developpez.com.
Merci également à Mahefasoa d'avoir pris le temps de le relire et de le corriger.

III-J - Liens

Tutoriel origine sur Tutos-Android