Consumir un servicio WCF localhost utilizando kSOAP2 en el emulador
He golpeado mi cabeza contra esta pared por un par de días ahora así que cualquier ayuda es muy apreciada.
Un poco de fondo, primero. Soy un desarrollador de WindowsMobile experimentado moviéndose a Android por lo que, por lo tanto, soy un noob en Java, Android, e incluso WCF. He hecho un montón de investigación sobre cómo consumir aplicaciones de WCF en Android usando kSOAP2, pero no importa lo que hago lo mejor que puedo llegar con un error de socket en Android debido a un tiempo fuera.
- Recomendaciones para el formato / protocolo de .NET Web Service para Android, iPhone, etc.
- No se puede conectar al servicio WCF en Android
- Llame a la variable de tipo de referencia WCF
- Leer WCF REST fecha de android
- Cómo WCF Webservices se puede probar localmente desde el emulador de Android?
Primero, creé una aplicación de servicio web en Visual Studio 2008 que no requiere parámetros y simplemente responde con un valor de cadena. El código del servicio web es el siguiente:
using System; using System.Collections.Generic; using System.Web; using System.Web.Services; namespace Sample { [WebService(Namespace = "http://sample.com/")] public class Service1 : System.Web.Services.WebService { [WebMethod] public string SayHello() { return "Hello, Android. From your friend, WCF"; } } }
Para este servicio web no he ajustado ninguna otra configuración ni he hecho ninguna modificación al archivo Web.config.
Cuando ejecuto el servicio abre mi navegador y señala a la url siguiente:
http://localhost:61554/Service1.asmx
A continuación, salté a Eclipse y creé un sencillo proyecto Android para consumir el servicio de WCF. Para empezar, cambié el archivo AndroidManifest.xml y le agregé esta declaración:
<uses-permission android:name="android.permission.INTERNET" />
Ahora para el código de mi clase de Android que se supone que hacer el trabajo pesado:
package com.sample; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import org.ksoap2.*; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.*; public class Sample extends Activity { TextView result; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); result = (TextView)findViewById(R.id.textViewResult); try { SoapObject Request = new SoapObject("http://sample.com/", "SayHello"); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; envelope.setOutputSoapObject(Request); HttpTransportSE androidHttpTransport = new HttpTransportSE("http://192.168.1.72:61554/Service1.asmx"); androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope); SoapObject response = (SoapObject)envelope.getResponse(); String resultValue = response.getProperty(0).toString(); result.setText(resultValue); } catch (Exception e) { result.setText(e.getMessage()); } } }
La línea de código que me está dando el error es:
androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope);
Cuando se ejecuta en el emulador el código llega a esa línea, se detiene durante un minuto o dos y luego cae en el bloque catch con una excepción de tiempo de espera.
¿Alguna idea sobre lo que podría faltar aquí? La ayuda es apreciada.
- Creación de una arquitectura cliente-servidor con estado en WCF
- ¿Cuándo es mejor no usar Phonegap?
- ¿Cómo hacer SSO basada en reclamaciones para aplicaciones Android e IPhone usando ADFS STS?
- Android post gzip
- Tener problemas para conectarse al servicio wcf en localhost desde el emulador de Android
- Cargar archivos de MS Word de Android a .Net WCF?
- Wcf progressive descargar
- Envío de una solicitud JSON HTTP POST desde Android
De acuerdo, finalmente descubrí mi problema (s). Varios factores estaban en juego que usted esperaría para alguien nuevo a estas tecnologías. Espero que mis errores salvarán a los demás algún tiempo.
El primer problema que tuve fue un error de parámetro en mi código. La línea
androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope);
era incorrecto en que debería haber enumerado el espacio de nombres para mi servicio web seguido por el nombre del método. Así que cambié esa línea a esto:
androidHttpTransport.call("http://sample.com/SayHello", envelope);
Después de este cambio todavía tenía la línea de lanzar una excepción, pero ahora estaba recibiendo una excepción diferente que era al menos una victoria moral. La nueva excepción decía lo siguiente:
expected START_TAG{http://schemas.xmlsoap.org/soap/envelope/} Envelope(position:START_TAG<html>@1:6 in java.io.InputStreamReader@d3el2cc4)
Este mensaje es desenfrenado en Internet, pero ninguna de las soluciones que encontré funcionó para mí. Después de muchas pruebas y errores encontré mi problema particular. Mi servicio web se crea en Visual Studio 2008 y lo estoy probando simplemente ejecutándolo dentro de Visual Studio y luego tratando de consumirlo desde mi emulador de Android. Resulta que hay una configuración de seguridad en el "sandbox" IIS de VS2008 que rechaza cualquier solicitud más allá de la PC local y aparentemente el emulador no se considera el PC local.
Para corregir ese problema tomé los pasos siguientes en Visual Studio 2008:
- Salir de Visual Studio y abrirlo con derechos administrativos (estoy usando Windows 7).
- Con mi proyecto abierto vi las propiedades del proyecto.
- En la pestaña "Web" cambié el botón de opción de la sección "Servidores" a "Usar servidor web IIS local", ingresé "http: // localhost / Sample" para mi URL de proyecto y pulsé el botón "Crear directorio virtual".
Después de completar estos pasos corrí mi servicio web de nuevo, lanzé mi aplicación para Android en el emulador y finalmente me puse por la línea que ha estado lanzando una excepción todo el tiempo. Esta vez, sin embargo, la siguiente línea lanzó una excepción. Otra victoria moral y un paso más cerca. Esta nueva excepción fue:
org.ksoap2.serialization.SoapPrimitive
Una búsqueda rápida de Google resolvió este para mí. Las líneas
SoapObject response = (SoapObject)envelope.getResponse(); String resultValue = response.getProperty(0).toString();
en mi código original necesitaba ser cambiado a esto:
SoapPrimitive response = (SoapPrimitive)envelope.getResponse(); String resultValue = response.toString();
Después de ese cambio tuve una aplicación de trabajo.
Código de trabajo final
Servicio Web (creado en Visual Studio 2008 y ejecutándose en el servidor web IIS local configurado en las propiedades del proyecto)
using System; using System.Collections.Generic; using System.Web; using System.Web.Services; namespace Sample { [WebService(Namespace = "http://sample.com/")] public class Service1 : System.Web.Services.WebService { [WebMethod] public string SayHello() { return "Hello, Android. From your friend, WCF"; } } }
Clase de Android
package com.sample; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import org.ksoap2.*; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.*; import org.ksoap2.serialization.SoapPrimitive; public class Sample extends Activity { TextView result; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); result = (TextView)findViewById(R.id.textViewResult); final String SOAP_ACTION = "http://sample.com/SayHello"; final String METHOD_NAME = "SayHello"; final String NAMESPACE = "http://sample.com/"; final String URL = "http://192.168.1.72/Sample/Service1.asmx"; try { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; envelope.setOutputSoapObject(request); HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); androidHttpTransport.call(SOAP_ACTION, envelope); SoapPrimitive response = (SoapPrimitive)envelope.getResponse(); String resultValue = response.toString(); result.setText(resultValue); } catch (Exception e) { result.setText(e.getMessage()); } } }
Acabo de luchar por este problema. Para acceder al host local en tu PC, necesitas el Dirección IP 10.0.2.2. Encontré la respuesta aquí. http://developer.android.com/resources/faq/commontasks.html#localhostalias . Ahora no consigo un tiempo de espera del zócalo pero consigo una excepción de XMLPullParser, que estoy pegado encendido.