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 :
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 :
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).
|
Sous Android Studio |
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();
}
}
}
}
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 :