Consommer un service Web en utilisant KSOAP2 sous Android

Christian Mbangala

Dans ce tutoriel, nous allons apprendre comment, à partir d'une application Android, faire appel à une méthode distante en vue d'effectuer un certain nombre d'opérations et de n'obtenir que le résultat final renvoyé par le service appelé. Pour dire simple, nous allons voir comment consommer un service web à partir d'un client Android en utilisant la bibliothèque KSoap2.

N'hésitez pas à commenter cet article ! Commentez ♪

- Titre : Consommer un service Web en utilisant KSOAP2 sous Android

- Auteur : Christian Mbangala

- Parution : 13 juillet 2015

- Licence : Copyright ® 2015 Christian Mbangala. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Prérequis

- II. Téléchargement de la bibliothèque KSOAP2

- III. Présentation du service web

- IV. Les carottes étant cuites, passons à l'acte

- IV-A. Ajout la bibliothèque KSaop2 téléchargée dans le classPath de notre projet

- IV-B. Création l'interface graphique de l'application (activity_main.xml)

- IV-C. Code métier (MainActivity.java)

- IV-D. Préparation de la requête

- IV-E. Création de l'enveloppe

- IV-F. Envoi de la requête au serveur

- IV-G. Récupération du résultat

- IV-H. Code Complet

- V. Conclusion

- VI. Remerciements

I - Prérequis

- Être un développeur Android.

- Être capable de créer un service web  si vous ne l'avez jamais fait auparavant, ce tutoriel vous sera d'une grande utilité (lien : https://netbeans.org/kb/docs/websvc/jax-ws.html).

- La bibliothèque Ksoap2 à télécharger ici : https://code.google.com/p/ksoap2-android/source/browse/m2-repo/com/google/code/ksoap2-android/ksoap2-android-assembly/3.4.0/ksoap2-android-assembly-3.4.0-jar-with-dependencies.jar.

- Enfin, un service web disponible et fonctionnel.

II - Téléchargement de la bibliothèque KSOAP2

Si je le présente ici, c'est parce que cela m'avait coûté des heures et des heures ce téléchargement et que je voudrais vous éviter de justesse cette peine.

Pour commencer, cliquez ici (https://code.google.com/p/ksoap2-android/source/browse/m2-repo/com/google/code/ksoap2-android/ksoap2-android-assembly/3.4.0/ksoap2-android-assembly-3.4.0-jar-with-dependencies.jar) et vous serez directement redirigé vers la page de téléchargement (ce qui vous évite en fait de fouiller tout le web avant d'y atterrir).

Ensuite, dans la page qui sera affichée, rendez-vous dans la partie le plus à droite et sous File info, faites un clic droit sur le lien View raw file et choisissez dans le menu contextuel qui s'affiche « enregistrer sous… ». Le fichier sera téléchargé et disponible dans votre emplacement de téléchargement.

III - Présentation du service web

J'ai créé un service web simple n'ayant qu'une seule méthode qui calcule la moyenne de trois nombres entiers (int) qui lui sont passés en paramètres et qui retourne un décimal (float) comme résultat de ce calcul. Cette méthode se présente comme suit :

1. /**

2. * Web service operation

3. */

4. @WebMethod(operationName = "calculMoyenne")

5. public float calculMoyenne(@WebParam(name = "a") int a, @WebParam(name = "b") int b, @WebParam(name = "c") int c) {

6. return (float) (a + b + c) / 3;

7. }

Quand vous allez créer le service web que vous voudrez consommer plus tard (depuis votre client Android), veillez retenir les informations suivantes :

1. L'URL du service web à consommer : celle qui vous permettra d'atteindre les méthodes que vous allez appeler (les services) ;

2. Le namespace : le nom du package dans lequel le fichier représentant votre service web est défini. Je ne vais pas entrer dans le détail, mais c'est hyper important ;

3. Le nom de la méthode à évoquer : trop simple à deviner n'est-ce pas ? Ce n'est rien d'autre que le nom de la méthode (ou des méthodes) du service web que vous allez appeler (consommer) depuis le client Android ;

4. Et pour finir, les noms de tous les paramètres que demande la méthode : il faut faire très attention à la casse.

Toutes ces informations dans mon cas se présentent de la manière suivante :

- URL : http://192.168.43.5:8080/WSCalcul/Calculs?WSDL ;

- NAMESPACE : http://webservice.tutows.com/ ;

- METHODNAME : calculMoyenne ;

- PARAMETRES : a, b, c.

IV - Les carottes étant cuites, passons à l'acte

Maintenant, tout étant prêt, nous allons passer à l'écriture de notre client Android. Suivez attentivement les étapes ci-dessous et tout vous sera facile.

IV-A - Ajout la bibliothèque KSaop2 téléchargée dans le classPath de notre projet

Créer un nouveau projet Android (comme vous en avez l'habitude d'ailleurs), copier KSaop2 de son emplacement et la coller dans le dossier libs de votre projet.

IV-B - Création l'interface graphique de l'application (activity_main.xml)

Elle aura trois zones de texte qui permettront chacune la saisie d'un nombre, un bouton dans lequel nous allons appeler le service web et un label en dessous du bouton pour affichage du résultat. Elle se présente comme suit :

Voici le code ayant permis d'aboutir à cette fin :

1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

2. xmlns:tools="http://schemas.android.com/tools"

3. android:layout_width="match_parent"

4. android:layout_height="match_parent"

5. android:orientation="vertical"

6. android:paddingBottom="@dimen/activity_vertical_margin"

7. android:paddingLeft="@dimen/activity_horizontal_margin"

8. android:paddingRight="@dimen/activity_horizontal_margin"

9. android:paddingTop="@dimen/activity_vertical_margin"

10. tools:context="com.abara.tutows.MainActivity" >

12. <EditText

13. android:id="@+id/txt_nombre1"

14. android:layout_width="fill_parent"

15. android:layout_height="wrap_content"

16. android:layout_marginTop="10dp"

17. android:ems="10"

18. android:hint="Premier nombre"

19. android:inputType="number" />

21. <EditText

22. android:id="@+id/txt_nombre2"

23. android:layout_width="fill_parent"

24. android:layout_height="wrap_content"

25. android:layout_marginTop="10dp"

26. android:ems="10"

27. android:hint="Deuxième nombre"

28. android:inputType="number" />

30. <EditText

31. android:id="@+id/txt_nombre3"

32. android:layout_width="fill_parent"

33. android:layout_height="wrap_content"

34. android:layout_marginTop="10dp"

35. android:ems="10"

36. android:hint="Troisième nombre"

37. android:inputType="number" />

39. <Button

40. android:id="@+id/btn_calculer"

41. android:layout_width="fill_parent"

42. android:layout_height="wrap_content"

43. android:layout_marginTop="10dp"

44. android:text="Calculer"

45. android:textStyle="italic"

46. android:typeface="serif" />

48. <TextView

49. android:id="@+id/lbl_resultat"

50. android:layout_width="fill_parent"

51. android:layout_height="wrap_content"

52. android:layout_marginTop="20dp"

53. android:ellipsize="end"

54. android:singleLine="true"

55. android:textColor="#FF0000"

56. android:textSize="20sp"

57. android:textStyle="italic|bold"

58. android:typeface="serif" />

60. </LinearLayout>

IV-C - Code métier (MainActivity.java)

Je vais directement dans le but du sujet qui concerne l'écriture du code du bouton « calculer » qui appelle le service web, récupère le résultat et l'affiche sur écran.

Pour commencer, nous rappelons que l'objectif est de consommer un service web ayant une méthode qui permet de calculer et renvoyer la moyenne de trois nombres entiers que nous aurions passés en paramètres. Nous avons déjà toutes les informations primordiales pour atteindre notre objectif à savoir :

- l'URL du service web (au fait l'adresse de son fichier wsdl) ;

- son namespace (qui n'est rien d'autre que le nom du package dans lequel la classe représentant notre service web est définie, suivi du caractère « / ») ;

- le nom de la méthode (c'est elle qui fera le calcul de la moyenne) ;

- les noms de tous les paramètres formels de la méthode ci-dessus (respecter la casse).

Ce qui nous amène à déclarer les constantes suivantes :

1. final String URL = "http://192.168.43.5:8080/WSTuto/Calculs?WSDL";

2. final String NAMESPACE = "http://webservice.tutows.com/";

3. final String METHODNAME = "calculMoyenne";

4. final String [] PARAMETRES = {"a", "b", "c"};

Pour éviter d'écrire plusieurs lignes, j'ai regroupé tous les paramètres dans un tableau. Croyez-moi, ce ne sera pas compliqué par la suite pour accéder à chacun d'entre eux.

N.B. En guise d'exemple j'ai utilisé les chaînes de caractères en dur. Cette pratique n'est pas recommandée dans un projet réel.

IV-D - Préparation de la requête

Nous allons commencer par créer un objet SoapObject pour préparer la requête à envoyer au serveur. Nous allons passer dans son constructeur le namespace (le premier paramètre requis), ainsi que le nom de la méthode à évoquer (deuxième paramètre).

1. SoapObject requete = new SoapObject(NAMESPACE, METHODNAME);

Ensuite, nous allons passer les paramètres à la méthode que nous souhaitons appeler. Pour passer ces paramètres, nous allons faire appel à la méthode addProperty() de l'objet requete que nous avons créé précédemment autant de fois que le nombre de paramètres à renseigner.

1. try{

2. requete.addProperty(parametres[0], Integer.parseInt(txt_nombre1.getText().toString()));

3. requete.addProperty(parametres[1], Integer.parseInt(txt_nombre2.getText().toString()));

4. requete.addProperty(parametres[2], Integer.parseInt(txt_nombre3.getText().toString())) ;

5. }catch(Exception e){

6. Log.e("MainActivity", e.getMessage());

7. }

Les valeurs des paramètres sont bien renseignées, notre requête est bel et bien prête.

IV-E - Création de l'enveloppe

Maintenant, nous allons créer une enveloppe que nous allons utiliser pour envoyer notre requête au serveur, mais aussi à travers laquelle nous traiterons le résultat que le serveur nous aurait renvoyé. Cet objet permet les échanges entre le client Android et le serveur (service web).

1. SoapSerializationEnvelope enveloppe = new SoapSerializationEnvelope(SoapEnvelope.VER11);

La construction de cet objet demande un entier dans le constructeur représentant la version du SOAP que le service web utilise. Dans mon cas, c'est la version 1.1, c'est pourquoi j'ai choisi la valeur SoapEnvelope.VER11.

Nous allons à présent configurer l'enveloppe que nous venons de créer en passant la requête qu'elle doit véhiculer.

1. enveloppe.setOutputSoapObject(requete);

N.B. Si votre service web est créé en .NET, vous serez dans l'obligation de le signaler dans votre enveloppe avant d'envoyer la requête au serveur pour assurer la compatibilité avec ce qui semble être l'encodage par défaut pour .Net -Services, sinon ça ne marchera pas. Pour ce faire, ajouter simplement la ligne ci-dessous :

1. enveloppe.dotNet = true;

IV-F - Envoi de la requête au serveur

Pour envoyer la requête contenue dans l'enveloppe, nous allons premièrement construire un objet qui fera le transport et lui passer l'URL de notre service web en paramètre de son constructeur. L'exécution de la requête sera faite dans un thread séparé (dans le code complet, j'ai créé une méthode dans laquelle j'ai placé cette exécution, ensuite j'ai utilisé l'AnsycTast pour l'appeler dans un thread séparé).

1. HttpTransportSE http_transport = new HttpTransportSE(URL);

Ensuite, exécutons la requête en appelant la méthode call(...) du httpTransportSE. Nous allons lui passer comme paramètres :

- un String (SoapAction), qui est la concaténation du « namespace » et du nom de la méthode à évoquer ;

- une enveloppe (SoapSerializationEnvelope).

1. http_transport.call(NAMESPACE + METHODNAME, enveloppe);

IV-G - Récupération du résultat

Pour récupérer le résultat renvoyé par le serveur, nous allons procéder de la manière suivante :

- tout d'abord, du fait qu'il s'agit d'un résultat de type primitif, nous allons créer un objet de type SoapPrimitive dans lequel nous allons mettre le résultat obtenu de l'enveloppe en appelant la méthode getResponse().

1. SoapPrimitive reponse = (SoapPrimitive)enveloppe.getResponse();

- ensuite, nous allons caster ce résultat en float. float resultat_float = Float.parseFloat(reponse.toString());.

Nous pouvons résumer l'envoi de la requête et la réception du résultat par (à appeler dans un thread séparé) :

1. try {

2. //Envoi de la requête

3. http_transport.call(NAMESPACE + METHODNAME, enveloppe);

4. //Récupération du résultat et traitement

5. SoapPrimitive reponse = (SoapPrimitive)enveloppe.getResponse();

6. resultat_float = Float.parseFloat(reponse.toString());

7. } catch (Exception e) {

8. Log.e("Erreur lors de l'envoi de la requête : ", e.getMessage());

9. }

IV-H - Code Complet

1. // Déclaration des variables et objets de l'interface graphique

3. EditText txt_nombre1;

4. EditText txt_nombre2;

5. EditText txt_nombre3;

7. Button btn_calculer;

9. TextView lbl_resultat;

11. ProgressDialog progression;

14. // Préparation des données pour le service web

16. final String URL = "http://192.168.43.5:8080/WSTuto/Calculs?WSDL";

17. final String NAMESPACE = "http://webservice.tutows.com/";

18. final String METHODNAME = "calculMoyenne";

19. final String [] PARAMETRES = {"a", "b", "c"};

21. // Inflation des composants graphiques

23. txt_nombre1 = (EditText)findViewById(id.txt_nombre1);

24. txt_nombre2 = (EditText)findViewById(id.txt_nombre2);

25. txt_nombre3 = (EditText)findViewById(id.txt_nombre3);

27. lbl_resultat = (TextView)findViewById(id.lbl_resultat);

29. btn_calculer = (Button)findViewById(id.btn_calculer);

32. // Méthode dans laquelle nous appelons le service web et récupérons le résultat renvoyé par ce dernier

34. public float executionRequete(String url, String namespace, String methodName, String [] parametres){

36. float resultat_float = 0f;

38. //Préparation de la requête

39. SoapObject requete = new SoapObject(namespace, methodName);

42. //Renseignement des valeurs des paramètres

43. try {

44. requete.addProperty(parametres[0], Integer.parseInt(txt_nombre1.getText().toString()));

45. requete.addProperty(parametres[1], Integer.parseInt(txt_nombre2.getText().toString()));

46. requete.addProperty(parametres[2], Integer.parseInt(txt_nombre3.getText().toString())) ;

47. } catch(Exception e) {

48. Log.e("MainActivity", e.getMessage());

49. }

51. //Création de l'enveloppe

52. SoapSerializationEnvelope enveloppe = new SoapSerializationEnvelope(SoapEnvelope.VER11);

54. //Ajout de la requête dans l'enveloppe

55. enveloppe.setOutputSoapObject(requete);

57. //Envoi de la requête et traitement du résultat

58. HttpTransportSE http_transport = new HttpTransportSE(url);

59. try {

60. http_transport.call(namespace + methodName, enveloppe);

61. SoapPrimitive reponse = (SoapPrimitive)enveloppe.getResponse();

62. resultat_float = Float.parseFloat(reponse.toString());

63. } catch (Exception e) {

64. Log.e("Erreur lors de l'envoi de la requête : ", e.getMessage());

65. }

66. //Retourner le résultat du calcul

67. return resultat_float;

68. }

70. // Classe qui étend AsyncTask pour l'exécution séparée

72. private class AppelWs extends AsyncTask<String, String, Float>{

74. @Override

75. protected void onPreExecute() {

76. // TODO Auto-generated method stub

77. progression = new ProgressDialog(MainActivity.this);

78. progression.setTitle("Appel au service web");

79. progression.show();

81. }

83. @Override

84. protected void onProgressUpdate(String... values) {

85. // TODO Auto-generated method stub

86. progression.setMessage(values[0]);

87. }

89. @Override

90. protected Float doInBackground(String... params) {

92. publishProgress("Calcul en cours...");

93. float r = executionRequete(URL, NAMESPACE, METHODNAME, PARAMETRES);

94. return r;

95. }

97. @Override

98. protected void onPostExecute(Float result) {

99. // Affichage du résultat dans le textView et disparition de la //progressDialog

100. lbl_resultat.setText("La moyenne donne : " + result);

101. progression.dismiss();

102. }

104. }

109. // Gestion du clic sur le bouton pour appeler le service web et afficher le résultat du calcul

111. btn_calculer.setOnClickListener(new View.OnClickListener() {

113. @Override

114. public void onClick(View v){

115. AppelWs ws = new AppelWs();

116. ws.execute();

117. }

118. });

V - Conclusion

Nous venons d'apprendre à consommer simplement et d'une grande facilité un service web depuis un client Android en se servant de la bibliothèque Ksoap2. Certes, ce n'était qu'une introduction, mais je vous assure que nous avons fait un très grand pas pour appréhender les concepts les plus avancés. Dans les prochains tutoriels, nous verrons comment exploiter un peu plus cette bibliothèque pour des opérations complexes telles que l'interrogation d'une base de données, la mise à jour… Bref, nous verrons comment traiter les données de type complexe (les objets).

Entre temps, vous remarques et suggestions me feront énormément plaisir et contribueront à l'amélioration de ce tutoriel.

VI - Remerciements

- Je tiens à remercier premièrement Feanorin de m'avoir donné le courage de rédiger cet article, de m'aider à avoir mon espace de rédaction et surtout pour la relecture technique de ce tutoriel. Grand merci à toi.

- Je remercie aussi Mickael Baron pour le temps qu'il a consacré pour la relecture technique de ce tutoriel malgré ses multiples occupations. Il m'a été d'un guide important tout au long de rédaction et correction de ce tutoriel, mais aussi dans la mise sous format developpez.com.

- Je ne pouvais pas oublier de remercier Grunk, lui qui n'a pas hésité de relire ce tutoriel que je lui avais demandé une relecture technique et qui m'a apporté des remarques constructives qui ont abouti à la présentation du code complet du petit projet d'essai mettant en évidence tout ce que nous avons appris ici.

- Je remercie au finish claudeLELOUP de sa disponibilité pour que ce tutoriel bénéficie d'une correction orthographique adéquate.