Consommation d’un WebService au format JSON dans une application Android

 

 

Contexte :

Reprise du cas FBCN. Dans ce projet "WebServiceFBCN", On avait créé, sous NetBeans, 2 webservices au format JSon. Le 1er permettait de récupérer le nom des courses et le 2ème les résultats d’une course dont le nom était passé en paramètre. Exemple de données retournées par le 2ème webservice :

[

{"nomCoureur":"HAMEL","nomCourse":"Rando Muco","place":1,"prenomCoureur":"Vivien","temps":"01:01:40"},{"nomCoureur":"JACOB","nomCourse":"Rando Muco","place":2,"prenomCoureur":"Anthony","temps":"01:02:30"},{"nomCoureur":"MADEC","nomCourse":"Rando Muco","place":3,"prenomCoureur":"Peter","temps":"01:03:50"}

]

 

Extrait de CourseResource :

image

 

Plan :

Sous NetBeans (Serveur web service)

Etape 1 :  Contrôler que les 2 webservices fonctionnent.

Sous Android (Client web service)

Etape 1 :  Créer l'appel au 1er webservice "noms des courses".

Etape 2 :  Parser les données JSON pour alimenter un spinner.

Etape 3 :  Placer un listener sur le spinner è Le choix sur ce spinner entrainera l'appel au second webservice "résultat de la course" et parsera les données JSON récupérées pour les afficher dans un ListView.


 

Exemple d'application Android :

image

 

 

image

Contrôler le web service

@GET // Méthode HTTP utilisée pour afficher les résultats d'une course dont le nom est passé en paramètre

    @Path("nomJSON")

    @Produces({MediaType.APPLICATION_JSON})

    public ArrayList<Courir> getJSON(@QueryParam("nomCourse") String pnomCourse)

    {

        ArrayList<Courir> lesResultats = GestionCourir.ResultatCourse(pnomCourse);

        return lesResultats;

    }

 

Ce web service sera appelé en ajoutant nomJSON?nomCourse=… à l'url.

Exemple : http://192.168.1.20:8080/WebServiceFBCN_ver2020/webresources/course/nomJSON?nomCourse=Rando Muco

 

 

Pour des "économies de ressources" vous pouvez arrêter NetBeans et démarrer GlassFish de façon indépendante (Vidéo4).

 

image

 

 

Sous Android Studio

1ère partie de l'application cliente Android

Objectif :   Parser les données ("nom des courses") et alimentation du spinner.

 

Consommer le 1er webservice (copier et accepter les import):

public class MainActivity extends AppCompatActivity
{
   
TextView txtAffichage;
   
Spinner spinCourse;
   
ArrayList<String> lesNomsDeCourses;
   
String typeDeContenu;
   
String lien = "";

   
// L'ADRESSE IP SERA A REMPLACER PAR L'IP DU POSTE CONTENANT LE WEB SERVICE
    String lienDeBase = "http://192.168.1.5:8080/WebServiceFBCN_ver2020/webresources/course";

   
String param = "";
   
URL urlCon;
   
HttpURLConnection urlConnection;

   
@Override
   
protected void onCreate(Bundle savedInstanceState)
    {
       
super.onCreate(savedInstanceState);
        setContentView(
R.layout.activity_main);
        initialisations();

       
lien = lienDeBase;
       
// Lancement de la tache asynchrone (obligatoire car l'appel à un WebService est une "tache longue")
       
AccesWebServices accesWS = new AccesWebServices();
       
String retourWS = "";
       
try
       
{
            retourWS =
accesWS.execute().get();
           
System.out.println("RETOUR2:" + retourWS);
        }
       
catch(Exception e)
        {
           
System.out.println("ERREUR APPEL DU WEBSERVICE : " + e.getMessage());
        }
       
/* PARSING DU TEXTE (retourWS) RETOURNé (format JSON) et création du tableau JSON */
       
JSONArray jTab = null;
       
try {
            jTab =
new JSONArray(retourWS);
        }
       
catch (Exception e)
        {
           
System.out.println("ERREUR TABLEAU JSON : " + e.getMessage());
        }
       
String[] nomCourse = new String[jTab.length()];
       
// Pour exploiter le tableau JSON
       
for (int i=0; i < jTab.length(); i++)
        {
           
try
           
{
               
nomCourse[i] = jTab.getJSONObject(i).getString("nom");
            }
           
catch (JSONException jse)
            {
               
System.out.println("ERREUR OBJET JSON : " + jse.getMessage());
            }
        }
       
/* FIN DU PARSING */

        // "Adaptation" du spinner a partir du tableau
       
SpinnerAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, nomCourse);
       
spinCourse.setAdapter(adapter);
    }
   
private void initialisations()
    {
       
txtAffichage = findViewById(R.id.txtResultat);
       
spinCourse = findViewById(R.id.cmbCourse);
       
/* On met un ecouteur sur le changement d'item du spinner (liste déroulante). Instruction pour l'instant en remarque */
       
spinCourse.setOnItemSelectedListener(new ClickSurSpinner());
    }

   
private class AccesWebServices extends AsyncTask<Void, Void, String>
    {
       
@Override
       
protected void onPreExecute()
        {
           
super.onPreExecute();
           
Toast.makeText(getApplicationContext(), "Début du traitement asynchrone", Toast.LENGTH_LONG).show();
        }
       
@Override
       
protected String doInBackground(Void... params)
        {
           
try
           
{
                
urlCon = new URL(lien);
               
urlConnection = (HttpURLConnection) urlCon.openConnection();
               
// Transformation du HttpUrlConnection en chaine
               
InputStream in = urlConnection.getInputStream();
                
BufferedReader rd = new BufferedReader(new InputStreamReader(in));
               
String retour = rd.readLine();
               
System.out.println("RETOUR1 : " + retour);
               
return retour;
            }
           
catch (Exception ex)
            {
               
return "ERREUR ASYNTASK : " + ex.getMessage();
            }
        }
    }

}


 

2ème partie de l'application cliente

Objectif :   Parser les données ("résultat de la course") et afficher ces données.

 

Le spinner doit provoquer l'affichage des résultats de la course sélectionnée. Ce qui donne le code suivant sur l'événement changeItem du spinner (à ajouter avant la dernière accolade fermante "}") :

private class ClickSurSpinner implements AdapterView.OnItemSelectedListener
{

   
@Override
   
public void onItemSelected(AdapterView<?> parent, View view,
                              
int position, long id) {
       
param = spinCourse.getSelectedItem().toString();
       
param = URLEncoder.encode(param);//change les caracteres inadequats
       
lien = lienDeBase + "/nomJSON?nomCourse=" + param;
       
System.out.println("PASSAGE : " + lien);

       
//Lancement de la tache asynchrone
       
AccesWebServices accesWS = new AccesWebServices();
       
try {
           
// Recupération et exploitation de la valeur de retour (de type String)
           
String rep2 = accesWS.execute().get();
           
txtAffichage.setText(rep2); // Juste pour le test

            /* PARSING DU TEXTE (retourWS) RETOURNé */
            // Création du tableau JSON
           
JSONArray jTab = new JSONArray(rep2);

           
String texte = "";
           
String nom, prenom, place, tps = "";
           
// Pour exploiter le tableau JSON
           
for (int i=0; i < jTab.length(); i++)
            {
                
try
               
{
                    nom =
jTab.getJSONObject(i).getString("nomCoureur");
                    prenom =
jTab.getJSONObject(i).getString("prenomCoureur");
                    place =
jTab.getJSONObject(i).getString("place");
                    tps =
jTab.getJSONObject(i).getString("temps");
                    texte += place +
"-" + nom + " " + prenom + " " + tps + "\n";
                }
               
catch (JSONException e)
                {

               
}
            }   //
FIN DU PARSING
           
txtAffichage.setText(texte);
        }
       
catch (Exception e)
        {
           
System.out.println("ERREUR CLICK SUR SPINNER : " + e.getMessage());
        }
    }

   
@Override
   
public void onNothingSelected(AdapterView<?> parent)
    {
    }
}

Ne pas oublier de décommenter la ligne (dans la procedure "initialisations") :

spinCourse.setOnItemSelectedListener(new ClickSurSpinner());


 

Exemple : http://192.168.1.20:8080/WebServiceFBCN_ver2020/webresources/course/nomJSON?nomCourse=Rando%20Muco

Données ramenées par le web service :

[{"nomCoureur":"HAMEL","nomCourse":"Rando Muco","place":1,"prenomCoureur":"Vivien","temps":"01:01:40"},{"nomCoureur":"JACOB","nomCourse":"Rando Muco","place":2,"prenomCoureur":"Anthony","temps":"01:02:30"},{"nomCoureur":"MADEC","nomCourse":"Rando Muco","place":3,"prenomCoureur":"Peter","temps":"01:03:50"},{"nomCoureur":"PARIS","nomCourse":"Rando Muco","place":4,"prenomCoureur":"Ryan","temps":"01:03:58"},{"nomCoureur":"VANNIER","nomCourse":"Rando Muco","place":5,"prenomCoureur":"Marc","temps":"01:04:35"},{"nomCoureur":"le_BRUN","nomCourse":"Rando Muco","place":6,"prenomCoureur":"Philipppe","temps":"01:05:40"},{"nomCoureur":"LE_CALVEZ","nomCourse":"Rando Muco","place":7,"prenomCoureur":"Alain","temps":"01:06:21"},{"nomCoureur":"JEGOU","nomCourse":"Rando Muco","place":8,"prenomCoureur":"Alan","temps":"01:07:00"},{"nomCoureur":"BEUVANT","nomCourse":"Rando Muco","place":9,"prenomCoureur":"Albert","temps":"01:07:25"},{"nomCoureur":"BARON","nomCourse":"Rando Muco","place":10,"prenomCoureur":"Lilian","temps":"01:10:27"}]

 

Ce qui donne sur l'application Android :

image