Nutzung von Webdiensten mit kSOAP
German (Deutsch) translation by Alex Grigorovich (you can also view the original English article)
In diesem Tutorial erfahren Sie, wie Sie Webdienste mithilfe der beliebten kSOAP-Bibliothek in einer Android-Anwendung nutzen. kSOAP ist eine seriöse Bibliothek, die von Entwicklern geliebt wird, die WSDL- (Web Service Definition Language) und SOAP-Nachrichten (Simple Object Access Protocol) analysieren müssen.
Einführung
Die kSOAP-Bibliothek ist eine elegante, leichte und effiziente SOAP-Clientbibliothek. Die Bibliothek ist Open Source, einfach zu verwenden und kann Ihnen die Mühe ersparen, einen benutzerdefinierten Parser zu programmieren. Es ist eine der vertrauenswürdigsten SOAP-Bibliotheken, die derzeit verfügbar ist, und wird häufig aktualisiert, was ein gutes Zeichen für jedes Open-Source-Projekt ist.
Es ist oft riskant, Open-Source-Software (OSS) in ein Projekt zu integrieren, da dies später zu unvorhergesehenen Problemen führen kann. Suchen Sie immer nach Kommentaren und Bewertungen anderer Entwickler, die die Bibliothek verwendet haben. Wenn sich das Projekt nicht in aktiver Entwicklung befindet, ist es möglicherweise besser, nach einer alternativen Lösung zu suchen.
Ziel dieses Tutorials ist es, Sie mit der kSOAP-Bibliothek vertraut zu machen. Zu Demonstrationszwecken verwenden wir einen einfachen Webservice von W3Schools. Der Webservice ist ein Umrechner von Fahrenheit in Celsius. Der Webservice akzeptiert einen Wert in Grad Fahrenheit und antwortet mit dem entsprechenden Wert in Grad Celsius. Wir gehen das Beispiel Schritt für Schritt durch. Am Ende dieses Tutorials zeigen wir das Ergebnis auf dem Gerät des Benutzers an.
1. Erste Schritte
Schritt 1: Projekteinrichtung
Starten Sie ein neues Android-Projekt und konfigurieren Sie es nach Belieben. Sie können gerne Ihre Lieblings-IDE verwenden, aber für dieses Tutorial verwende ich IntelliJ IDEA.
In der Manifestdatei des Projekts müssen Sie angeben, dass die Anwendung eine Verbindung zum Internet herstellen darf. Wir werden auch die SDK-Zielversion sowie die SDK-Mindestversion angeben. Sehen Sie sich die unten gezeigte Manifest-Datei an.
1 |
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/> |
2 |
<uses-permission android:name="android.permission.INTERNET"/> |
Schritt 2: Herunterladen von kSOAP
Versuchen Sie immer, die neueste stabile Version einer Bibliothek zu verwenden, oder aktualisieren Sie die Bibliothek, die Sie in einer Anwendung verwenden, nachdem ein größeres Update veröffentlicht wurde. Es hat sich aus verschiedenen Gründen bewährt, die Abhängigkeiten eines Projekts auf dem neuesten Stand zu halten, z. B. aus Sicherheitsgründen und Fehlerbehebungen. In diesem Tutorial verwenden wir Version 3.1.1 der kSOAP-Bibliothek, die Sie auf der Download-Seite des Projekts finden. Nachdem Sie die kSOAP-Bibliothek heruntergeladen haben, fügen Sie sie dem libs-Ordner Ihres Projekts hinzu.
Schritt 3: Hinzufügen von kSOAP zu Ihrem Projekt
Um die kSOAP-Bibliothek in Ihrem Projekt zu verwenden, müssen Sie sie Ihrem Projekt hinzufügen. Ich zeige Ihnen, wie Sie es mit IntelliJ IDEA hinzufügen. Die Schritte können etwas anders sein, wenn Sie eine andere IDE verwenden, aber die Idee ist dieselbe. Wählen Sie in IntelliJ IDEA im Menü Datei die Option Projektstruktur... aus, öffnen Sie den Bereich Module, klicken Sie auf die Plus-Schaltfläche unten im rechten Bereich und wählen Sie Bibliothek aus. Navigieren Sie zum Ordner libs und wählen Sie die kSOAP-Bibliothek aus. Schauen Sie sich zur Verdeutlichung die beiden Bilder unten an.






Die kSOAP-Bibliothek sollte jetzt als Abhängigkeit Ihres Projekts sichtbar sein. Klicken Sie auf das Kontrollkästchen neben der kSOAP-Bibliothek, um sie Ihrem Projekt hinzuzufügen. Nachdem wir die Bibliothek zu unserem Projekt hinzugefügt haben, ist es an der Zeit, sie zu verwenden. Wenn Sie IntelliJ IDEA verwenden, sollte Ihr Projekt dem unten gezeigten ähnlich sein.



2. W3Schulen-Webdienst
Die Verwendung der kSOAP-Bibliothek zur Nutzung eines Webdienstes umfasst eine Reihe von Schritten. Bevor wir uns jedoch direkt mit der Verwendung der kSOAP-Bibliothek befassen, ist es nützlich, Ihnen ein wenig mehr über den von uns verwendeten Webservice zu erzählen.
Besuchen Sie die Website des W3Schools-Webdienstes, den wir in diesem Tutorial verwenden. Sie werden sehen, dass es zwei Operationen gibt, CelsiusToFahrenheit und FahrenheitToCelsius. Der Name jeder Operation ist selbsterklärend. Die URL des Webdienstes ist die Basis-URL, die wir verwenden, um eine Verbindung zum Webdienst herzustellen.
Wenn Sie auf der W3Schools-Website einen Vorgang auswählen, wird Ihnen ein Beispiel für die vom Webdienst erwartete Anforderung sowie die Antwort des Webdienstes angezeigt. Sehen Sie sich das folgende Code-Snippet an, bei dem es sich um eine Beispielanfrage handelt, die der Webdienst erwartet. Achten Sie genau auf die SOAPAction im Code-Snippet. Wir werden es etwas später in diesem Tutorial verwenden.
1 |
POST /webservices/tempconvert.asmx HTTP/1.1 |
2 |
Host: www.w3schools.com |
3 |
Content-Type: text/xml; charset=utf-8 |
4 |
Content-Length: length |
5 |
SOAPAction: "http://www.w3schools.com/webservices/FahrenheitToCelsius" |
6 |
<!--?xml version="1.0" encoding="utf-8"?-->
|
7 |
string |
Das nächste Code-Snippet zeigt eine Beispielantwort des Webdienstes.
1 |
HTTP/1.1 200 OK |
2 |
Content-Type: text/xml; charset=utf-8 |
3 |
Content-Length: length |
4 |
<!--?xml version="1.0" encoding="utf-8"?-->
|
5 |
string |
3. Verwendung von kSOAP
Schritt 1: Erstellen eines Umschlags
Als erstes müssen wir einen SOAP-Umschlag mit der SoapSerializationEnvelope-Klasse (org.ksoap2.serialization.SoapSerializationEnvelope) erstellen, die Sie aus der kSOAP-Bibliothek importieren müssen. Sehen Sie sich das folgende Code-Snippet an, in dem ich eine Instanz der SoapSerializationEnvelope-Klasse initialisiert habe.
1 |
SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request); |
Die Methode getSoapSerializationEnvelope ist in der kSOAP-Bibliothek nicht definiert. Es ist eine Hilfsmethode, die ich erstellt habe, um die Arbeit mit der kSOAP-Bibliothek etwas einfacher zu machen. Die Methode gibt den SOAP-Envelope zurück, den wir für den Rest des Beispiels benötigen. Sehen Sie sich unten die Implementierung von getSoapSerializationEnvelope an.
1 |
private final SoapSerializationEnvelope getSoapSerializationEnvelope(SoapObject request) { |
2 |
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); |
3 |
envelope.dotNet = true; |
4 |
envelope.implicitTypes = true; |
5 |
envelope.setAddAdornments(false); |
6 |
envelope.setOutputSoapObject(request); |
7 |
|
8 |
return envelope; |
9 |
}
|
Die Methode getSoapSerializationEnvelope akzeptiert eine SoapObject-Instanz, die die Anforderung darstellt. Wir werden in wenigen Minuten sehen, wie Sie die Anfrage erstellen. Beim Erstellen einer Instanz der SoapSerializationEnvelope-Klasse wird die SoapEnvelope-Version durch Übergabe von SoapEnvelope.VER11 festgelegt, was der kSOAP-Bibliothek mitteilt, dass wir SOAP 1.1 verwenden werden. Wir setzen die dotNet-Eigenschaft des Umschlags auf true, da der Webdienst, den wir verwenden werden, auf dem .NET-Framework von Microsoft ausgeführt wird.
1 |
envelope.dotNet = true; |
Schritt 2: Konfigurieren des Umschlags
Jetzt ist es an der Zeit, den SOAP-Envelope zu konfigurieren, indem Sie die Anforderungsinformationen festlegen. Beginnen Sie mit dem Importieren der SoapObject-Klasse (org.ksoap2.serialization.SoapObject) und sehen Sie sich den folgenden Codeausschnitt an, um zu sehen, wie Sie den Umschlag konfigurieren. Wir beginnen mit der Erstellung einer Instanz der SoapObject-Klasse, die zwei Parameter erfordert, einen Namespace und einen Methodennamen. Sie können der Anforderung mithilfe der addProperty-Methode zusätzliche Eigenschaften hinzufügen, wie unten gezeigt. In unserem Beispiel verwende ich addProperty, um der Anfrage den Wert in Grad Fahrenheit hinzuzufügen.
1 |
String methodname = "FahrenheitToCelsius"; |
2 |
SoapObject request = new SoapObject(NAMESPACE, methodname); |
3 |
request.addProperty("Fahrenheit", fValue); |
Sie fragen sich vielleicht, woher NAMESPACE kommt. Es ist eine private statische Zeichenfolge, die an anderer Stelle in der Anwendung definiert ist, wie Sie unten sehen können.
1 |
private static final String NAMESPACE = "http://www.w3schools.com/webservices/"; |
Schritt 3: Anfrage erstellen
Um die Anfrage an den Webservice zu senden, müssen wir eine HTTP-Transportanfrage erstellen. Dazu verwenden wir die HttpTransportSE-Klasse (org.ksoap2.transport.HttpTransportSE). Schauen Sie sich das Beispiel unten an.
1 |
HttpTransportSE ht = getHttpTransportSE(); |
Wie Sie vielleicht schon vermutet haben, ist getHttpTransportSE eine weitere Hilfsmethode, mit der Sie schnell ein HTTP-Transportobjekt erstellen können. Dadurch ist es weniger mühsam, bei jedem Webservice-Aufruf ein HTTP-Transportobjekt zu erstellen. Sehen Sie sich die Implementierung unten an. Um eine HttpTransportSE-Instanz zu erstellen, benötigen wir nur die Basis-URL des Webdienstes, die eine weitere private statische Zeichenfolge ist, wie Sie unten sehen können.
1 |
private final HttpTransportSE getHttpTransportSE() { |
2 |
HttpTransportSE ht = new HttpTransportSE(Proxy.NO_PROXY,MAIN_REQUEST_URL,60000); |
3 |
ht.debug = true; |
4 |
ht.setXmlVersionTag("<!--?xml version=\"1.0\" encoding= \"UTF-8\" ?-->"); |
5 |
return ht; |
6 |
}
|
1 |
private static final String MAIN_REQUEST_URL = "http://www.w3schools.com/webservices/tempconvert.asmx"; |
In getHttpTransportSE konfigurieren wir auch das HttpTransportSE-Objekt. Indem wir Proxy.NO_PROXY als erstes Argument des Konstruktors übergeben, geben wir an, dass kein Proxy für die Anfrage verwendet wird. Das dritte Argument des Konstruktors legt das Sitzungs-Timeout in Millisekunden fest. Um das Debuggen zu vereinfachen, setzen wir auch die debug-Eigenschaft des Objekts auf true. Alle auftretenden Probleme werden in LogCat protokolliert.
Schritt 4: Senden der Anfrage
Es ist an der Zeit, die SOAP-Anfrage an den Webdienst zu senden. Wir tun dies über HTTP mit den zuvor erstellten Transport- und Envelope-Objekten. Das HTTP-Transportobjekt verfügt über eine call-Methode, mit der die zuvor erstellte SOAP-Aktion und der Umschlag hinzugefügt werden.
1 |
ht.call(SOAP_ACTION, envelope); |
SOAP_ACTION ist ein weiterer privater statischer String, wie Sie unten sehen können.
1 |
private static final String SOAP_ACTION = "http://www.w3schools.com/webservices/FahrenheitToCelsius"; |
Schritt 5: Verarbeitung der Antwort
Wenn der Webdienst eine Antwort zurücksendet, müssen wir sie verarbeiten und alle möglicherweise ausgelösten Fehler behandeln. Die Daten können wir dann dem Nutzer anzeigen. Sehen Sie sich das folgende Code-Snippet an, in dem wir die Antwort mit der Methode getResponse aus dem Antwortumschlag extrahieren.
1 |
SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse(); |
Ich verwende einen SoapPrimitive-Typ, aber Sie können auch eine SoapObject-Instanz verwenden, wenn die Antwort vom Webdienst XML ist. Sie können dann die SoapObject-Instanz verwenden, um die Antwortwerte abzurufen und in einem Array zu speichern. Rufen Sie toString für das SoapPrimitive-Objekt auf, um die Antwort in eine einfache Zeichenfolge zu konvertieren, um sie in Ihrer Anwendung zu verwenden.
Schauen Sie sich das nächste Code-Snippet an, in dem ich eine Methode getCelsiusConversion implementiert habe. Die Methode akzeptiert eine String-Variable als einziges Argument. Die Variable wird der SOAP-Anforderung als Eigenschaft hinzugefügt, wie wir zuvor in diesem Tutorial gesehen haben. Die Variable, die die Methode verbraucht, ist der Wert in Grad Fahrenheit. Dieser Wert wird an den Webservice gesendet und von diesem verarbeitet und wir erhalten eine Antwort in Grad Celsius zurück.
1 |
public String getCelsiusConversion(String fValue) { |
2 |
String data = null; |
3 |
String methodname = "FahrenheitToCelsius"; |
4 |
|
5 |
SoapObject request = new SoapObject(NAMESPACE, methodname); |
6 |
request.addProperty("Fahrenheit", fValue); |
7 |
|
8 |
SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request); |
9 |
|
10 |
HttpTransportSE ht = getHttpTransportSE(); |
11 |
try { |
12 |
ht.call(SOAP_ACTION, envelope); |
13 |
testHttpResponse(ht); |
14 |
SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse(); |
15 |
|
16 |
List COOKIE_HEADER = (List) ht.getServiceConnection().getResponseProperties(); |
17 |
|
18 |
for (int i = 0; i < COOKIE_HEADER.size(); i++) { |
19 |
String key = COOKIE_HEADER.get(i).getKey(); |
20 |
String value = COOKIE_HEADER.get(i).getValue(); |
21 |
|
22 |
if (key != null && key.equalsIgnoreCase("set-cookie")) { |
23 |
SoapRequests.SESSION_ID = value.trim(); |
24 |
Log.v("SOAP RETURN", "Cookie :" + SoapRequests.SESSION_ID); |
25 |
break; |
26 |
}
|
27 |
}
|
28 |
data = resultsString.toString(); |
29 |
|
30 |
} catch (SocketTimeoutException t) { |
31 |
t.printStackTrace(); |
32 |
} catch (IOException i) { |
33 |
i.printStackTrace(); |
34 |
} catch (Exception q) { |
35 |
q.printStackTrace(); |
36 |
}
|
37 |
return data; |
38 |
}
|
Ich verwende zwei Strings in getCelsiusConversion, data und methodname. Die data-Variable wird von der Methode zurückgegeben, nachdem der Webdienst eine Antwort zurückgesendet hat, während methodname den Namen der Operation des Webdienstes speichert, auf den wir abzielen und der in der SoapObject-Instanz verwendet wird.
Möglicherweise haben Sie die for-Schleife in getCelsiusConversion bemerkt, die nicht Teil der zuvor besprochenen Schritte ist. Bei der Arbeit mit komplexeren Webservices ist es wichtig, die aktuelle Sitzung im Auge zu behalten. Im folgenden Snippet speichere ich die Sitzung und verfolge sie jedes Mal, wenn ich den Webdienst aufrufe.
1 |
for (int i = 0; i < COOKIE_HEADER.size(); i++) { |
2 |
String key = COOKIE_HEADER.get(i).getKey(); |
3 |
String value = COOKIE_HEADER.get(i).getValue(); |
4 |
if (key != null && key.equalsIgnoreCase("set-cookie")) { |
5 |
SoapRequests.SESSION_ID = value.trim(); |
6 |
Log.v("SOAP RETURN", "Cookie :" + SoapRequests.SESSION_ID); |
7 |
break; |
8 |
}
|
9 |
}
|
4. Erstellen der Benutzeroberfläche
Jetzt, da die harte Arbeit hinter uns liegt, ist es an der Zeit, das zu nutzen, was wir gerade geschaffen haben. Zum Abschluss dieses Tutorials zeige ich Ihnen, wie Sie eine einfache Benutzeroberfläche erstellen, um einen Wert in Grad Fahrenheit in einen Wert in Grad Celsius umzuwandeln und das Ergebnis auf dem Gerät des Benutzers anzuzeigen.
Schritt 1: Erstellen Sie das Layout
Zuerst müssen wir eine XML-Datei im Layoutordner des Projekts erstellen. Sehen Sie sich das folgende Code-Snippet an. Es ist eine einfache Illustration einer in XML erstellten Benutzeroberfläche.
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
3 |
android:orientation="vertical" |
4 |
android:layout_width="fill_parent" |
5 |
android:layout_height="fill_parent" /> |
6 |
<EditText
|
7 |
android:layout_width="200dp" |
8 |
android:layout_height="wrap_content" |
9 |
android:layout_gravity="center_horizontal" |
10 |
android:hint="Fahrenheit" |
11 |
android:inputType="number" |
12 |
android:id="@+id/value_to_convert" /> |
13 |
|
14 |
<Button
|
15 |
android:layout_width="200dp" |
16 |
android:layout_height="wrap_content" |
17 |
android:layout_gravity="center_horizontal" |
18 |
android:text="Convert to Celsius" |
19 |
android:id="@+id/convert" /> |
20 |
|
21 |
<TextView
|
22 |
android:layout_width="fill_parent" |
23 |
android:layout_height="wrap_content" |
24 |
android:gravity="center_horizontal" |
25 |
android:textSize="30dp" |
26 |
android:id="@+id/answer" /> |
27 |
</LinearLayout>
|
Wir erstellen drei Komponenten, eine EditText-Instanz, eine Button-Instanz und eine TextView-Instanz. Die EditText-Instanz wird verwendet, um den Wert einzugeben und zu erfassen, den wir an den Webdienst senden möchten. Die Schaltfläche wird verwendet, um den Thread auszuführen, der getCelsiusConversion aufruft, und die Textansicht zeigt die Antwort an, die wir vom Webdienst erhalten.
Schritt 2: Erstellen Sie die Aktivität
Der nächste Schritt besteht darin, eine Activity-Instanz zu erstellen, um das gerade erstellte Layout anzuzeigen. Sehen Sie sich das folgende Code-Snippet an. Dies sollte nicht allzu überraschend sein, wenn Sie bereits Android-Anwendungen entwickelt haben.
1 |
package com.example.KsoapExample; |
2 |
|
3 |
import android.app.Activity; |
4 |
import android.os.Bundle; |
5 |
|
6 |
public class MyActivity extends Activity { |
7 |
/**
|
8 |
* Called when the activity is first created.
|
9 |
*/
|
10 |
@Override
|
11 |
public void onCreate(Bundle savedInstanceState) { |
12 |
super.onCreate(savedInstanceState); |
13 |
setContentView(R.layout.main); |
14 |
}
|
15 |
}
|
Nachdem wir uns nun um die Benutzeroberfläche gekümmert haben, können wir alles zusammenbringen. Sehen Sie sich das nächste Code-Snippet an, um zu sehen, wie dies geschieht.
1 |
package com.example.KsoapExample; |
2 |
|
3 |
import android.app.Activity; |
4 |
import android.os.Bundle; |
5 |
|
6 |
public class MyActivity extends Activity { |
7 |
private TextView txt; |
8 |
private String celsius; |
9 |
/**
|
10 |
* Called when the activity is first created.
|
11 |
*/
|
12 |
@Override
|
13 |
public void onCreate(Bundle savedInstanceState) { |
14 |
super.onCreate(savedInstanceState); |
15 |
setContentView(R.layout.main); |
16 |
|
17 |
final EditText edt = (EditText)findViewById(R.id.value_to_convert); |
18 |
Button btn = (Button)findViewById(R.id.convert); |
19 |
txt = (TextView)findViewById(R.id.answer); |
20 |
|
21 |
btn.setOnClickListener(new View.OnClickListener() { |
22 |
@Override
|
23 |
public void onClick(View v) { |
24 |
if (edt.length() > 0) { |
25 |
getCelsius(edt.getText().toString()); |
26 |
} else { |
27 |
txt.setText("Fahrenheit value can not be empty."); |
28 |
}
|
29 |
}
|
30 |
});
|
31 |
}
|
32 |
}
|
In onCreate setzen wir einen Listener auf die Schaltfläche btn. Wir überprüfen auch, ob ein Wert in das Eingabefeld eingegeben wurde, bevor wir ihn an den Webservice senden. Im Schaltflächenklick-Listener wird der an getCelsius übergebene Wert in eine Zeichenfolge umgewandelt, da der Webdienst einen Zeichenfolgenwert erwartet. Die Implementierung von getCelsius ist nicht schwierig, wie Sie unten sehen können.
1 |
private final void getCelsius(final String toConvert) { |
2 |
new Thread(new Runnable() { |
3 |
|
4 |
@Override
|
5 |
public void run() { |
6 |
SoapRequests ex = new SoapRequests(); |
7 |
celsius = ex.getCelsiusConversion(toConvert); |
8 |
handler.sendEmptyMessage(0); |
9 |
}
|
10 |
}).start(); |
11 |
}
|
In getCelsius wird ein neuer Thread erstellt, der ausgeführt wird und eine Instanz der Klasse erstellt, die getCelsiusConversion implementiert. Wenn wir eine Antwort vom Webservice erhalten, senden wir eine Nachricht an einen Handler, um die Benutzeroberfläche zu aktualisieren, indem wir dem Benutzer den Wert in Grad Celsius anzeigen.
1 |
public Handler handler = new Handler(new Handler.Callback() { |
2 |
|
3 |
@Override
|
4 |
public boolean handleMessage(Message msg) { |
5 |
switch (msg.what) { |
6 |
|
7 |
case 0: |
8 |
txt.setText(celsius); |
9 |
break; |
10 |
}
|
11 |
return false; |
12 |
}
|
13 |
});
|
Im Handler aktualisieren wir die TextView-Instanz mit dem Wert, den wir vom Webdienst erhalten haben. Sehen Sie sich das Endergebnis unten an.



Abschluss
Sie sollten jetzt in der Lage sein, die kSOAP-Bibliothek zu einem Projekt hinzuzufügen und sie zu nutzen, um Anfragen an einen Webdienst zu senden, der das SOAP-Protokoll verwendet. Die Arbeit mit der kSOAP-Bibliothek wird mit ein wenig Übung einfacher und ich empfehle Ihnen daher, den Webservice zur Konvertierung von Celsius in Fahrenheit auszuprobieren. Probieren Sie die Android-Beispielanwendung aus, die Teil des Tutorials ist, um zusätzliche Hilfe zu erhalten.



