TD 2 - Synchronisation avec un serveur

De $1

Table des matières
aucun titre
     

Etape 1 - Synchronisation avec le serveur 

Dans cette étape, nous allons utiliser le protocole HTTP pour envoyer les données du formulaire vers un serveur (mis à votre disposition pour ce TP).

Le serveur expose un web service REST qui accetpte  et renvoie des données sous format JSON.  Les ressources exposées sont des personnes sur lesquelles vous pouvez effectuer les actions CRUD (Create, Read, Update, Delete). L'URI de la ressource personne est : http://95.142.161.35:8080/person/

Exemple: Pour créer un utilisateur

Methode : 'POST'

Content-type: 'application/json'

Modèle de données à envoyer 

{
"nom": "Edouard", 
"prenom" : "Amosse", 
"sexe": "Masculin", 
"telephone" : "123456789", 
"email" : "eamosse@gmail.com", 
"createdby" : "Amosse", 
"password" : "1234"
}

Modèle de réponse retournée par le serveur 

  • {
    • nom"Edouard",
    • prenom"Amosse",
    • sexe"Masculin",
    • telephone"123456789",
    • createdby"Amosse",
    • connectedtrue,
    • createdAt"2014-10-15T20:19:20.365Z",
    • updatedAt"2014-10-15T20:19:20.365Z",
    • id"543ed6c8761b3a277050a478"
    }

Vous allez modifier l'activity EnregistrerActivity pour envoyer les données du formulaire vers le serveur.  

Ajoutez une classe interne dans l'activity qui hérite de AsyncTask.  AsyncTask est une classe générique proposée par le SDK vous permettant d'effectuer des requetes HTTP de manière assynchrone. Ceci nous permet de ne pas bloquer le thread principal de l'application au moment déeffectuer la requete HTTP. 

 

class RegisterTask extends AsyncTask<Person,Void,Person>{

@Override
protected Person doInBackground(Person... people) { //Effectuer la requete vers les WS ici         String reponseDuWebService; //Convertir la reponse en objet JSON //Créer une personne à partir du JSON
return person;
}

@Override
protected void onPreExecute() {
super.onPreExecute(); //Afficher un loading "Patientez, inscription en cours..."
}

@Override
protected void onPostExecute(Person person) {
super.onPostExecute(aVoid); //Enlever le loading //Traiter la person if (person!=null) {         }else{         }         //Renvoyer vers le login         //Fermer l'activité Enregistrer
}

Dans cette classe vous avez trois méthodes: 

doInBackground : est déstinée à effectuer des actions en tache de fond.  Cette methode crée automatiquement un autre thread et il n'est pas possible de modifier l'interface de l'application dans cette methode car les elements de l'interface sont gérés par le thread principale d'Android (la UIThread). 

onPreExecute: Vous permet d'effectuer des actions avant de passer la main à la méthode doInBackground.  Vous pouvez par exemple afficher un loading, invitant l'utilisateur à patienter. 

onPostExecute: Cette méthode est appeleé à la fin de l'execution de la méthode doInBacground, vous indiquant que la fin de l'execution des méthodes doInBackground. Vous pouvez enlever le loading à ce moment là, et mettre à jour l'interface si besoin est. 

Cette classe accepte aussi un ensemble de paramère lui permettant de communiquer avec l'activité appelante ou d'echanger des informations avec les méthodes. Le premier représente les paramètres qui seront passés à la méthode doInBackground, ces paramètres sont passés comme étant un tableau (remarquez les ... après Void dans doInBackground, en Java ils modélisent un tableau de dimension inconnue).  Le deuxième représente un progressbar si on veut afficher l'état d'avancement de la tache asynchrone (par exemple le pourcentage d'un téléchargement) et le troisième est le type de retour de la méthode doInBackground ainsi que le paramaètre de la méthode onPostExecute. Ici nous avons utilisé Void, vous pouvez au besoin les changer si vous sentez le besoin. 

Modifiez la méthode doInBacground pour effectuer une requete HTTP vers le serveur.  Complétez la méthode et importez les packages qu'il faut. 

try{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);

// add header

post.setHeader("Content-Type", "application/json");
JSONObject obj = new JSONObject();
obj.put("prenom", person.getPreom());
obj.put("nom", person.getNom());
.....
StringEntity entity = new StringEntity(obj.toJSONString());

post.setEntity(entity);

HttpResponse response = client.execute(post);
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + post.getEntity());
System.out.println("Response Code : " +
response.getStatusLine().getStatusCode());

BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));

StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}

System.out.println(result.toString()); return result.toString();
} catch (Exception e){

}

Vous pouvez modifier la méthode onPreExecute pour afficher un loading en attendant l'envoi des données au serveur. Ajoutez une méthode showProgressDialog pour afficher un loading.

ProgressDialog progressDialog;
public void showProgressDialog(boolean isVisible) {
if (isVisible) {
if(progressDialog==null) {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage(this.getResources().getString(R.string.please_wait));
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(true);
progressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
progressDialog = null;
}
});
progressDialog.show();
}
}
else {
if(progressDialog!=null) {
progressDialog.dismiss();
}
}
}

Appelez la méthode showProgressDialog dans onPreExecute de la classe AsyncTask. 

@Override
protected void onPreExecute() {
super.onPreExecute();
showProgressDialog(true);
}

Enlevez le loading dans la méthode onPostExecute. Traitez la réponse qui est un json et afficher si oui ou non l'utilisateur est inscrit.

@Override
protected void onPostExecute(String theResponse) {
super.onPostExecute(aVoid);
showProgressDialog(false); Toast.makeText(this,R.string.inscription_ok, Toast.LENGTH_LONG).show();
}

Dans l'action onClick du bouton enregistrer, appelez la classe que vous venez de créer et qui fait la requete asynchrone. 

@Override
public void onClick(View view) {
if(view.getId()==R.id.register){
//Valider votre formulaire
new MyTask().execute();
}
}

Etape 3 - Connexion 

Inspirez vous de l'étape 2 pour permettre à un utilisateur de se connecter sur le serveur. 

URL : http://95.142.161.35:8080/person/login

Content-Type : application/json 

Accept : application/json 

Methode : POST

Données à envoyer: 

{
"email" : "eamosse@gmail.com",
"password" : "1234"
}

 Modèle de réponse en cas d'erreur 

{
"success" : false,
"message" : "Nom d'utilisateur ou mot de passe incorrecte"
}

Modèle de réponse en cas de succès

{
  "success": true,
  "user": {
    "nom": "Edouard",
    "prenom": "Amosse",
    "sexe": "Masculin",
    "telephone": "123456789",
    "email": "eamosse@gmail.com",
    "createdby": "Amosse",
    "password": "1234",
    "connected": true,
    "createdAt": "2014-10-15T20:27:09.998Z",
    "updatedAt": "2014-10-15T20:27:09.998Z",
    "id": "543ed89ed9573e6e76a02490"
  }
}

Je suis sure qu'il existe des librairies qui permettent de faire plus simple non :)

  1. La librairie Gson de Google permet de faire du mapping POJO <-> Json 
    1. https://github.com/google/gson
    2. http://www.studytrails.com/java/json...troduction.jsp
  2. La librarie Android Query permet de faire des requetes asynchrone plus simplement 
    1. https://code.google.com/p/android-query/

Et comme vous etes super intelligent, votre travail consiste à modifier l'application pour utiliser Gson pour traiter les Json et Android Query pour traiter les requetes asynchrones.  Ca va nous aider pour la suite.