java - servicios - Llamar a un servicio web de soap en Android
web service android studio sql server (3)
Esta pregunta ya tiene una respuesta aquí:
- Cómo llamar a un servicio web SOAP en Android [cerrado] 26 respuestas
Necesito hacer una llamada a un servicio web soap en un dispositivo Android. He estado leyendo muchos artículos en stackoverflow y en otras páginas, viendo videos ... Pero lo he intentado todo y no puedo hacer que funcione en mi dispositivo Android, y no puedo probar con un emulador, porque mi computadora no puede manejar ninguno de ellos, por lo que no sé si el error está en el código o si se trata de un problema de mi dispositivo Android.
El diseño xml es solo un EditText, un Button y un TextView.
En este enlace, puede ver la solicitud xml que necesito enviar al servicio web (¿debería usar SOAP 1.1 o SOAP 1.2?) Http://www.webservicex.net/globalweather.asmx?op=GetCitiesByCountry
Este es mi código real, y lo he intentado de muchas otras maneras, y ninguno de ellos me ha funcionado. ¿Alguna ayuda? (Los valores url, namespace, soap_action y method_name son okey, ¿no?)
package com.example.doazdoas.webservice_prueba;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.os.AsyncTask;
import android.widget.Toast;
import static android.content.ContentValues.TAG;
public class MainActivity extends Activity{
private TextView textResult;
private Button buttonSend;
String NAMESPACE = "http://www.webserviceX.NET/";
String METHOD_NAME = "GetCitiesByCountry";
String SOAP_ACTION = NAMESPACE + METHOD_NAME;
String URL = "http://www.webservicex.net/globalweather.asmx?WSDL";
private Object resultsRequestSOAP = null;
HttpTransportSE androidHttpTransport;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.textResultado);
buttonSend = (Button)findViewById(R.id.buttonEnviar);
//setContentView(tv);
}
public void onClickEnviar(View view){
AsyncCallWS task = new AsyncCallWS();
task.execute();
}
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
@Override
protected Void doInBackground(Void... params) {
Log.i(TAG, "doInBackground");
sendRequest();
return null;
}
@Override
protected void onPostExecute(Void result) {
Log.i(TAG, "onPostExecute");
Log.d("dump Request: " ,androidHttpTransport.requestDump);
Log.d("dump response: " ,androidHttpTransport.responseDump);
}
}
public void sendRequest(){
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
//SoapObject
request.addProperty("@CountryName", "SPAIN");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
androidHttpTransport = new HttpTransportSE(URL);
try
{
androidHttpTransport.call(SOAP_ACTION, envelope);
resultsRequestSOAP = envelope.getResponse();
String[] results = (String[]) resultsRequestSOAP;
textResult.setText( results[0]);
}
catch (Exception aE)
{
aE.printStackTrace ();
}
}
}
¿Ha considerado hacer las solicitudes de jabón sin el uso de bibliotecas? Tuve el mismo problema antes y me llevó a descubrir que las bibliotecas harán su trabajo más difícil, especialmente cuando se trata de hacer cambios en la estructura de la solicitud. Así es como se realiza una solicitud de jabón sin el uso de bibliotecas: en primer lugar, deberá saber cómo usar SOAP Ui, que es una aplicación de Windows. Puede importar su archivo wsdl aquí y si la sintaxis es correcta, obtendrá una pantalla que muestra el cuerpo de la solicitud para su servicio web. Puede ingresar valores de prueba y obtendrá una estructura de respuesta. Este enlace lo guiará sobre cómo usar soap ui https://www.soapui.org/soap-and-wsdl/working-with-wsdls.html
Ahora en el código de Android:
Crearemos una clase llamada runTask que extienda la tarea asincrónica y use http para enviar el cuerpo de la solicitud y obtener la respuesta de la solicitud:
private class runTask extends AsyncTask<String, String, String> {
private String response;
String string = "your string parameter"
String SOAP_ACTION = "your soap action here";
String stringUrl = "http://your_url_here";
//if you experience a problem with url remove the ''?wsdl'' ending
@Override
protected String doInBackground(String... params) {
try {
//paste your request structure here as the String body(copy it exactly as it is in soap ui)
//assuming that this is your request body
String body = "<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">" +
"<soap:Body>"+
"<GetCitiesByCountryResponse xmlns="http://www.webserviceX.NET">"+
"<GetCitiesByCountryResult>"+string+"</GetCitiesByCountryResult>"+
"</GetCitiesByCountryResponse>"+
"</soap:Body>"+
"</soap:Envelope>";
try {
URL url = new URL(stringUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDefaultUseCaches(false);
conn.setRequestProperty("Accept", "text/xml");
conn.setRequestProperty("SOAPAction", SOAP_ACTION);
//push the request to the server address
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(body);
wr.flush();
//get the server response
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
response = builder.toString();//this is the response, parse it in onPostExecute
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
/**
* @see AsyncTask#onPostExecute(Object)
*/
@Override
protected void onPostExecute(String result) {
try {
Toast.makeText(this,"Response "+ result,Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
Ahora solo ejecuta la clase y observa cómo sucede la magia:
runTask runner = new runTask();
runner.execute();
Puede analizar la respuesta utilizando un analizador DOM o SAX para obtener los valores deseados. Siéntase libre de pedir más aclaraciones.
Puedes hacer cualquier operación relacionada con la interfaz de usuario en doInBackGround
, así que onPostExecute
en la onPostExecute
de onPostExecute
PostExecute.
Porque doInBackGround
no es un hilo de IU. Lea el documento AsyncTask con cuidado. Cualquiera que sea la información que está devolviendo de doInBackGround
, se está tomando como entrada en onPostExecute
.
Así que cambie su código de la siguiente manera,
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
@Override
protected String[] doInBackground(Void... params) {
Log.i(TAG, "doInBackground");
String[] data = sendRequest();
return data;
}
@Override
protected void onPostExecute(String[] result) {
Log.i(TAG, "onPostExecute");
if(result != null && result.length > 0){
textResult.setText( results[0]);
}
}
}
private String[] sendRequest(){
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
//SoapObject
request.addProperty("@CountryName", "SPAIN");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
androidHttpTransport = new HttpTransportSE(URL);
try
{
androidHttpTransport.call(SOAP_ACTION, envelope);
resultsRequestSOAP = envelope.getResponse();
String[] results = (String[]) resultsRequestSOAP;
}
catch (Exception aE)
{
aE.printStackTrace ();
}
}
clase privada AsyncCallWS extiende AsyncTask {
private String[] data;
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
@Override
protected String[] doInBackground(Void... params) {
Log.i(TAG, "doInBackground");
data = sendRequest();
return data;
}
@Override
protected void onPostExecute(String[] result) {
Log.i(TAG, "onPostExecute");
if(result != null && result.length > 0){
Log.d("dump Request: " ,androidHttpTransport.requestDump);
Log.d("dump response: " ,androidHttpTransport.responseDump);
textResult.setText( result[0]);
}else{
Log.d("Error","There''s no answer");
}
}
}
Lo cambié y ahora es así ... Pero siempre se imprime que no hay respuesta