Muy grande respuesta SOAP – Android- fuera de error de memoria

Tengo una aplicación donde necesito descargar una gran cantidad de datos vía una llamada de SOAP a un webservice en la aplicación cuando está funcionada por primera vez. La respuesta se envía a una función que convierte el XML y almacena los datos en un archivo db.

Los datos son más de 16 MB de tamaño y tengo un java.lang.OutOfMemoryError cada vez.

Modificar el webservice para dar cantidades más pequeñas de datos no es una opción.

¿Hay una manera de poder descargar los datos grandes? Algo como un InputStream tal vez?

Este es mi codigo

public Protocol[] getProtocols() { String METHOD_NAME = "GetProtocols"; String SOAP_ACTION = "urn:protocolpedia#GetProtocols"; Log.d("service", "getProtocols"); SoapObject response = invokeMethod(METHOD_NAME, SOAP_ACTION); return retrieveProtocolsFromSoap(response); } private SoapObject invokeMethod(String methodName, String soapAction) { Log.d(TAG, "invokeMethod"); SoapObject request = GetSoapObject(methodName); SoapSerializationEnvelope envelope = getEnvelope(request); return makeCall(envelope, methodName, soapAction); } 

¿Alguien puede sugerir qué se debe hacer en este caso?

Gracias y saludos Mukul

Dos estrategias para ayudarle a resolver este problema:

  1. Guarde su flujo XML de SOAP directamente en el disco mientras lo descarga. No lo guarde en la memoria.
  2. Analizarlo utilizando un analizador de estilo SAX, donde no carga todo el DOM en memoria, sino que lo analiza en trozos.

Dependiendo del tipo de XML que esté manejando, el uso de los analizadores SAX suele ser más difícil en el código; Usted tendrá que hacer un seguimiento de muchas cosas usted mismo, y no será capaz de "saltar" de sección a sección de su árbol DOM. Pero el consumo de memoria será mucho menor.

Sin embargo, tenga en cuenta que muchas bibliotecas de comunicación de red de "alto nivel" normalmente cargan todo el XML DOM en la memoria, lo cual podría ser el caso aquí. Es probable que tenga que crear y administrar la conexión HTTP usted mismo y, a continuación, analizar manualmente el resultado.

Sólo una actualización, encontré que el método de "llamada" en AndroidHttpTransport se estaba quedando sin memoria en esta línea –

  if (debug) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) break; bos.write(buf, 0, rd); } bos.flush(); buf = bos.toByteArray(); //Goes out of memory here responseDump = new String(buf); is.close(); is = new ByteArrayInputStream(buf); 

La llamada a toByteArray tiene una gran cantidad de memoria, por lo que para superar esto, en lugar de convertir la respuesta a una matriz de bytes, ahora directamente escribirlo en un archivo XML, y esto se guarda en una ubicación de mi elección. Aquí –

 if (debug) { FileOutputStream bos = new FileOutputStream("/data/data/com.mypackage.myapp/response.xml"); byte[] buf = new byte[1048576]; int current = 0; int i=0; int newCurrent = 0; while ((current = inputStream.read(buf)) != -1) { newCurrent = newCurrent + current; Log.d("current", "Current = " + current + " total = "+newCurrent+" i = "+i++); bos.write(buf, 0, current); } bos.flush(); } 

El dispositivo ya no se queda sin memoria, y tengo un método de análisis personalizado que toma este XML y lo escribe en el DB.

¡Fijo!

He descargado / copiado HttpTransportSE java clase de aquí (después de copiado, algunos errores de código pueden ocurrir, pero son todos rápido fijable) y agregó a mi paquete:

 https://github.com/mosabua/ksoap2-android/blob/master/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java 

Eliminado de mi clase de conexión esta fila:

 import org.ksoap2.transport.HttpsTransportSE; 

Y sustituí este código en mi nuevo archivo HttpTransportSE.java:

 if (debug) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) break; bos.write(buf, 0, rd); } bos.flush(); buf = bos.toByteArray(); //Goes out of memory here responseDump = new String(buf); is.close(); is = new ByteArrayInputStream(buf); } 

con este

 if (debug) { FileOutputStream bos = new FileOutputStream(file); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) { break; } bos.write(buf, 0, rd); } bos.flush(); } 

Donde "file" es un objeto de archivo simple como new File ("/ sdcard /", "myFile.xml") por ejemplo

  • Soap Client en Android para acceder a las API de Salesforce
  • SOAP - Respuesta XML muy grande - OutOfMemoryError
  • ¿Es posible la llamada a SOAP webservice usando Retrofit?
  • No se puede conectar al servicio WCF en Android
  • Cómo pasar el valor al parámetro enum de la bandera en el servicio Soap (servicio ASMX) Desde la aplicación android
  • Envío de imágenes de la galería al servicio web mediante SOAP
  • Cómo mostrar la respuesta de cadena de db como uno por uno en Android?
  • Eliminación del campo i: type en la solicitud SOAP generada por kSoap2 en Android
  • Cómo rastrear / depurar este error SOAP => parece que no tenemos ningún documento XML
  • Android, envío de XML a través de HTTP POST (SOAP)
  • Cómo hacer la solicitud de correo de jabón utilizando la biblioteca Volley en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.