Descarga de información Web Service Json

48 views
Skip to first unread message

Fray

unread,
Apr 1, 2015, 9:02:18 PM4/1/15
to desarrollad...@googlegroups.com
Buenas Noches compañeros.
No se si me puedan ayudar actualmente poseo una aplicación que descarga información mediante un web service (servicio desarrollado en php y consultas mysql) el servicio funciona bien y me genera un Json que le entrego a la aplicación pero me pasa que en algunos dispositivos me muestra errores de memoria, es como si el json fuece demaciado grande para ser procesado y la aplicación termina por detenerce.
El objetivo es lograr descargar mas de 60000  registros en el menor tiempo posible.

El metodo utilizado para realizar esta tarea es el siguiente:

               public int descargaClientes3(SQLiteDatabase db,ConfiguracionBeans configuracionBeans, int myProgress, ProgressDialog dialog,String zonaVentas, int ruta) {
int retorno=0;
String SQL = "";
ArrayList<String> listSQL2;
String SOAP_ACTION = "pollServer";
String METHOD_NAME = "pollServer";
String NAMESPACE = configuracionBeans.getServer();
String URL = configuracionBeans.getUrlDescarga()+"?wsdl";

SoapObject soapclient = new SoapObject(NAMESPACE, METHOD_NAME);
SoapObject parameters = new SoapObject(NAMESPACE, METHOD_NAME);
parameters.addProperty("value", "DESCARGA_CLIENTES3");
parameters.addProperty("zona", zonaVentas);
parameters.addProperty("ruta", ruta);
soapclient.addProperty(METHOD_NAME, parameters);

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(soapclient);
HttpTransportSE httpTransportSE = new HttpTransportSE(URL,120000);
httpTransportSE.debug=true;

try {
httpTransportSE.call(SOAP_ACTION, envelope);
String response =  envelope.getResponse().toString();
Log.d("JSON Response:",""+response);
if(response != null)
{
try{
JSONObject jsonObj = new JSONObject(response);
listSQL2 = new ArrayList<String>();
String confRs="RestrinccionProveedor";
restrinccionProveedorQuery.deleteAll(db);
configuracionArray = jsonObj.getJSONArray(confRs);
for(int i =0; i<configuracionArray.length();i++)
{
JSONObject c= configuracionArray.getJSONObject(i);
SQL = " INSERT OR REPLACE INTO table_name (campos...)  " +
"VALUES ('" +c.getString("Id") +"', campos del json...);";
listSQL2.add(SQL);
}
// Cargo la barra de estado
myProgress=myProgress+2;
if(myProgress<100)
{
          dialog.setProgress(myProgress);
          SystemClock.sleep(100);
        }  
 
insertDatos(listSQL2,db);
 
}catch(JSONException e)
{
e.printStackTrace();
retorno=3;
}
}else{
Log.e("ERROR:","Problema en la lectura del json.");
retorno=3;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
retorno=2;
} catch (XmlPullParserException e) {
////log.v("TEST", "xml wrong");
// TODO Auto-generated catch block
e.printStackTrace();
retorno=2;
}
return retorno;
}


              private void insertDatos(ArrayList<String> listSQL,SQLiteDatabase db){
if(listSQL != null && listSQL.size() > 0){
if(db!=null){
db.beginTransaction();
try{
for(int i = 0; i < listSQL.size();i++)
{
db.execSQL(listSQL.get(i));
}
db.setTransactionSuccessful();
}catch(Exception e)  {
System.out.println("Error:   transacción"+e);
}finally{
db.endTransaction();
}
}
listSQL.clear();
}
   System.gc(); //liberacion de memoria 
   Runtime.getRuntime().gc();
}



Actualmente el proceso funciona muy bien si el servicio me retorna menos de 2000 registros al aunmentar la cantidad me empieza generar errores de memoria y forzar cierres.

De antemano muchas gracias por sus colaboraciones.

Gabriel Pozo

unread,
Apr 2, 2015, 9:13:19 AM4/2/15
to desarrollad...@googlegroups.com

Cual es la salida del log cuando ocurre el error? Otra cosa, el código desde mi smartphone no lo veo bien, estas utilizando un hilo separado como una async task para la petición?


--
Para participar es necesario que leas detenidamente las normas del grupo: http://goo.gl/8h8ez2
---
Has recibido este mensaje porque estás suscrito al grupo "desarrolladores-android" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a desarrolladores-a...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a desarrollad...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/desarrolladores-android.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/desarrolladores-android/9ef3e9ee-2431-410e-93e3-7bcfda405ec4%40googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Felipe Ceballos

unread,
Apr 3, 2015, 2:43:27 PM4/3/15
to desarrollad...@googlegroups.com
Hola Gabriel mira error que el log cat me muestra es:
Out of memory on a 12640462-byte allocation.
...
FATAL EXCEPTION: AsyncTask #1
 Process: com.altipalAx, PID: 11429
 java.lang.RuntimeException: An error occured while executing doInBackground()
 at android.os.AsyncTask$3.done(AsyncTask.java:300)
  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
  at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
  at java.util.concurrent.FutureTask.run(FutureTask.java:242)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
  at java.lang.Thread.run(Thread.java:841)
 Caused by: java.lang.OutOfMemoryError
  at java.lang.String.<init>(String.java:255)
  at java.lang.String.<init>(String.java:171)
  at java.lang.String.<init>(String.java:141)
  at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:184)
  at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:95)
  at extras.Download.descargaAcuerdosComercial(Download.java:2119)
  at com.altipalAx.Rutas$Sincronizar.doInBackground(Rutas.java:302)
  at com.altipalAx.Rutas$Sincronizar.doInBackground(Rutas.java:1)
  at android.os.AsyncTask$2.call(AsyncTask.java:288)
  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
  ... 3 more
 android.view.WindowLeaked: Activity com.altipalAx.Rutas has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{21af4048 V.E..... R.....ID 0,0-465,346} that was originally added here
  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:376)
  at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
  at android.app.Dialog.show(Dialog.java:286)
  at com.altipalAx.Rutas$Sincronizar.onPreExecute(Rutas.java:276)
  at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587)
  at android.os.AsyncTask.execute(AsyncTask.java:535)
  at com.altipalAx.Rutas.llamar_conexion(Rutas.java:211)
  at com.altipalAx.Rutas.onclickRuta(Rutas.java:204)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at android.view.View$1.onClick(View.java:3846)
  at android.view.View.performClick(View.java:4466)
  at android.view.View$PerformClick.run(View.java:18540)...

Si efectivamente un metodo async task para la peticion.
Mira de esta forma:

class Sincronizar extends AsyncTask<String, Void, Void> {
DatabaseHelper databaseHelper = new DatabaseHelper(Rutas.this);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
AlertDialog ad2 = new AlertDialog.Builder(Rutas.this.getApplicationContext()).create();

private final ProgressDialog dialog2 = new ProgressDialog(Rutas.this);
private final ProgressDialog dialog4 = new ProgressDialog(Rutas.this);
int retorno;
public void onPreExecute() {
mLockScreenRotation();
myProgress = 0;
dialog = new ProgressDialog(Rutas.this);
dialog.setMessage("DESCARGANDO\nINFORMACIÓN...");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.setMax(100);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
}

@Override
protected Void doInBackground(String... params) {
Looper.myLooper();
try {
Looper.prepare();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}

//Limpio la tabla donde almaceno la informacion
AcuerdoComercialQuery acuerdoComercialQuery = new AcuerdoComercialQuery();
acuerdoComercialQuery.deleteAll(db);
retorno=download.descargaClientes3(db,configuracionBeans,myProgress=myProgress+2,dialog,zonaVentas,ruta);
return null;
}

@Override
protected void onPostExecute(Void result) {
dialog.cancel();
// 0 Ok
// 2 Problema conexion
// 3 Problema o error al leer los datos.
if(retorno == 0)
{
//Intent con el que continuo con el proceso.
}

if (retorno ==2) {
this.dialog4.setMessage("El equipo tiene problemas de conectividad, inténtelo nuevamente, si el problema persiste por favor comuníquese con su operador celular para verificar la conexión de datos");
this.dialog4.setCanceledOnTouchOutside(false);
this.dialog4.setCancelable(false);
this.dialog4.setButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
dialog4.dismiss();
}
});
this.dialog4.show();
return;
}
}
}


Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Andrés Felipe Ceballos Meneses

Roger Isaac Navarro Perez

unread,
Apr 3, 2015, 3:16:57 PM4/3/15
to desarrollad...@googlegroups.com

Yo uso el ksoap para descargar miles de registros y lo que hago es paginar, los puedes buscar de 1000 en 1000, hay un par de cosas a considerar en una conexión móvil, el time out de la conexión en android y las restricciones de los operadores de telefonía, algunos operadores tienen un time out y algunos tienen un límite en cuestión del tamaño de la información que se puede transmitir, dependiendo del tipo de tecnología que usen.

Saludos.

Gabriel Pozo

unread,
Apr 4, 2015, 11:48:35 AM4/4/15
to desarrollad...@googlegroups.com
Felipe, creo que Roger respondió tu consulta :D
Porque crees que te da este tipo de error? Caused by: java.lang.OutOfMemoryError ;)

Un par de cosas muy importantes, te recomiendo ver esto:
http://www.aprendiendodeandroidymas.com/2013/11/como-puedo-usar-el-logcat-para-ayudarme.html

Es muy importante tener la salida de un error que capturas en un catch en tu log ;) para no perderte información muy valioso :D
Nunca olvides imprimir esa información, seguramente allí hay más datos que te van a ayudar a depurar tu aplicación.

Segundo en tu función descargaClientes3, veo un try dentro de otro try y ningun log en los catch :P :P eso es una extremadamente mala combinación ;) Y otra pequeña crítica (recuerda que esto es siempre para mejorar ;) ) para mi, devolver un int como código de error lo podes dejar para C o algún otro lenguaje :D
Podrías crear tu propia excepción, y hacer que en caso de que falle tu función lanzarla ;) hasta podrías devolver un Enum que seguramente va a ser más descriptivo ;)


Reply all
Reply to author
Forward
0 new messages