| Tipica pantalla cuando estas programando... Escribes código por 5 minutos y estas debugeandolo por cerca de 5 horas... |
Bueno. Algo "entretenido" anoche, me puse a programar en android... y esta aplicación dentro de su código tenía una llamada a una petición http.
Bueno, yo estaba programando usando como target un sistema de nivel 8 (Android 2.2 Froyo) y mi emulador era una máquina con el mismo sistema operativo. No habían problemas, si bien se pegaba un poco al arrancar (lo cual era causado por que la descarga se realizaba en el hilo de ejecución principal).
Bueno, yo estaba programando usando como target un sistema de nivel 8 (Android 2.2 Froyo) y mi emulador era una máquina con el mismo sistema operativo. No habían problemas, si bien se pegaba un poco al arrancar (lo cual era causado por que la descarga se realizaba en el hilo de ejecución principal).
Pero entonces, decidí tomar mi propio dispositivo, el cual estaba cargado con una versión diferente de android, tenía 4.2, claro que en un celular super viejo (del año 2010?), pero ocurrió un problema extraño… La aplicación simplemente no arrancaba. Entonces, me puse en posición fetal por cerca de una hora pensando en que podría hacer que arranque en el emulador, pero que no arranque en el dispositivo real. Entonces, en el modo debug apareció un error más menos extraño…
01-18 00:39:46.849: W/System.err(1213): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
Ese error no aparecía en el debug de la aplicación anterior. Pero esa ‘W’ presente en el error, indicaba que era una advertencia… y luego de buscar en google un rato y no encontrar nada de nada, decidí realizar una búsqueda mas acotada y guiarme por esa 'W' antes que vi.
La búsqueda me llevó a StackOverflow -hermosa esa pagina- en donde la opinión de todos era clara.
Simplemente, mi problema era que de mala suerte, justo después de la versión de android que estaba ocupando, los tipos de google, implementaron el sistema de "Modo Estricto", el cual es una solución para poder atrapar errores y leaks en las aplicaciones, capturando y proveendo de una solución directa al desarrollador.
Pero mala la volah, yo estoy programando en 2.1... ¿entonces que hago? Ahí, en ese punto NO EXISTEN esas clases...
La solucion: La API de reflexión de java.
No cambia mucho por el resto. La gracia de este método, es que si la clase existe, termina ejecutando el equivalente a estas lineas.
Ahora, si no estamos presentes frente a un sistema que no contenga estas clases, simplemente arrojara una excepción. Y todos felices, hemos usado reflexión para poder desactivar una característica que no sabemos si estará disponible o no.
Claro que, desactivar esa funcionalidad del android es algo riesgoso. En las plataformas superiores a 4.1, cuando la UI se queda "colgada" por el motivo que sea (en este caso la carga de contenido desde web) por mas de 5 segundos, manda el aviso de que la aplicación se esta tardando mucho y le da la opción al usuario de ser cerrada. Y no queremos que el usuario piense que eso es un bug... no no no no! Es una caracteristica!~ ♥
La forma correcta de descargar contenido, es usando hilos o tareas asincronas o cualquier modo que evite que la ejecución del hilo principal (que controla la UI) se cuelgue y no actualice.
En el siguiente post, explicaré como es la forma correcta de solucionar el problema que vomitó el programa la primera vez sin tener que desactivar "la seguridad" del modo estricto.
Nyan!~
La búsqueda me llevó a StackOverflow -hermosa esa pagina- en donde la opinión de todos era clara.
If you look at this Android documentation, it explains NetworkOnMainThreadException: The exception that is thrown when an application attempts to perform a networking operation on its main thread.So, depending on OS version, there may be enforcement (exception throwing) of the policy that you not make network requests on the UI thread. This could explain why your code works on a device, and not on an emulator (if they have different Android versions). You could change the ThreadPolicy. But as an alternative, I'd suggest you look again at the statement in the Android docs. They heavily discourage performing network operations on the main thread, and I'd certainly agree with them.So, rather than changing the policy to make it legal, you might consider changing your code, so that your getResponse() method is not called on the UI thread.Typically, you would use AsyncTask to do the work in the background. |
Simplemente, mi problema era que de mala suerte, justo después de la versión de android que estaba ocupando, los tipos de google, implementaron el sistema de "Modo Estricto", el cual es una solución para poder atrapar errores y leaks en las aplicaciones, capturando y proveendo de una solución directa al desarrollador.
Pero mala la volah, yo estoy programando en 2.1... ¿entonces que hago? Ahí, en ese punto NO EXISTEN esas clases...
La solucion: La API de reflexión de java.
Class<?> strictModeClass = Class.forName(Bueno. La explicación es relativamente simple.
"android.os.StrictMode", true, Thread.currentThread()
.getContextClassLoader());
Class<?> threadPolicyClass = Class.forName(
"android.os.StrictMode$ThreadPolicy", true, Thread
.currentThread().getContextClassLoader());
Class<?> threadPolicyBuilderClass = Class.forName(
"android.os.StrictMode$ThreadPolicy$Builder", true,
Thread.currentThread().getContextClassLoader());
Method setThreadPolicyMethod = strictModeClass.getMethod(
"setThreadPolicy", threadPolicyClass);
Method permitAllMethod = threadPolicyBuilderClass
.getMethod("permitAll");
Method buildMethod = threadPolicyBuilderClass
.getMethod("build");
Constructor<?> threadPolicyBuilderConstructor = threadPolicyBuilderClass
.getConstructor();
Object threadPolicyBuilderObject = threadPolicyBuilderConstructor
.newInstance();
Object obj = permitAllMethod.invoke(threadPolicyBuilderObject);
Object threadPolicyObject = buildMethod.invoke(obj);
setThreadPolicyMethod.invoke(strictModeClass,
threadPolicyObject);
Class<?> strictModeClass = Class.forName(Ese con esa linea, uno captura la clase (en caso de existir) y la almacena en una variable de tipo clase.
"android.os.StrictMode", true, Thread.currentThread()
.getContextClassLoader());
Method setThreadPolicyMethod = strictModeClass.getMethod(Este otro tipo de lineas, permite "extraer" un método y encapsularlo en una variable. En este caso, es capturado de la misma clase que anteriormente se extrajo.
"setThreadPolicy", threadPolicyClass);
Constructor<?> threadPolicyBuilderConstructor = threadPolicyBuilderClassY luego con esa, llegamos al constructor usando el mismo sistema...
.getConstructor();
Object threadPolicyBuilderObject = threadPolicyBuilderConstructorFinalmente, debemos que capturar los objetos que van a entregar cada uno de los métodos descritos y comenzamos a invocar.
.newInstance();
Object obj = permitAllMethod.invoke(threadPolicyBuilderObject);
Object threadPolicyObject = buildMethod.invoke(obj);
setThreadPolicyMethod.invoke(strictModeClass,
threadPolicyObject);
No cambia mucho por el resto. La gracia de este método, es que si la clase existe, termina ejecutando el equivalente a estas lineas.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Ahora, si no estamos presentes frente a un sistema que no contenga estas clases, simplemente arrojara una excepción. Y todos felices, hemos usado reflexión para poder desactivar una característica que no sabemos si estará disponible o no.
Claro que, desactivar esa funcionalidad del android es algo riesgoso. En las plataformas superiores a 4.1, cuando la UI se queda "colgada" por el motivo que sea (en este caso la carga de contenido desde web) por mas de 5 segundos, manda el aviso de que la aplicación se esta tardando mucho y le da la opción al usuario de ser cerrada. Y no queremos que el usuario piense que eso es un bug... no no no no! Es una caracteristica!~ ♥
La forma correcta de descargar contenido, es usando hilos o tareas asincronas o cualquier modo que evite que la ejecución del hilo principal (que controla la UI) se cuelgue y no actualice.
En el siguiente post, explicaré como es la forma correcta de solucionar el problema que vomitó el programa la primera vez sin tener que desactivar "la seguridad" del modo estricto.
Nyan!~
No hay comentarios:
Publicar un comentario