Aplicación de Android se estrella en Samsung Galaxy S3 (sin error de memoria)

Tengo una aplicación para Android que toma algunas imágenes, las redimensiona y las envía al servidor back-end. Esta aplicación funciona perfectamente bien en todos los otros teléfonos (pan de jengibre y sándwich de helado), excepto Samsung Galaxy S3. Cada vez que toma las imágenes e intenta volver a tamaño, se queda sin memoria. Inicialmente pensé que era un problema con la parte de volver a dimensionar e implementé el objeto de mapa de bits con insamplesize y probé todo, pero todavía seguía fallando. Entonces me di cuenta de que cuando la aplicación se lanza al principio, está utilizando una gran cantidad de memoria. En HTC y todos los demás teléfonos, cuando mi aplicación se lanza, que utiliza hasta alrededor de 4 MB, pero en el Galaxy S3, que utiliza alrededor de 30 MG – casi 10 veces más. No puedo imaginar lo que haría que usar hasta que la memoria mucho más. Estoy reciclando todos los objetos y diseños correctamente (creo). Aquí está el código que tengo que cambiar el tamaño de la imagen:

public static void resizeImage(String pathOfInputImage, String pathOfOutputImage) { try { int inWidth = 0; int inHeight = 0; float factor; InputStream in = new FileInputStream(pathOfInputImage); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); inWidth = options.outWidth; inHeight = options.outHeight; in.close(); in = null; options = null; if (inWidth > inHeight) { factor = (float) inHeight / 480; } else { factor = (float) inWidth / 480; } options = new BitmapFactory.Options(); Bitmap roughBitmap; if(Build.VERSION.SDK_INT < 12) { System.gc(); } try { in = new FileInputStream(pathOfInputImage); options.inSampleSize = 4; roughBitmap = BitmapFactory.decodeStream(in, null, options); } catch (OutOfMemoryError e) { roughBitmap = Utils.fetchRoughBitmap(pathOfInputImage, factor); } finally { roughBitmap = Utils.fetchRoughBitmap(pathOfInputImage, factor); } in.close(); in = null; boolean rotate = false; Bitmap rotatedBitmap = null; if (isNeedToRotate(pathOfInputImage)) { rotate = true; Matrix m = new Matrix(); m.postRotate(90); try { rotatedBitmap = Bitmap.createBitmap(roughBitmap, 0, 0, roughBitmap.getWidth(), roughBitmap.getHeight(), m, true); } catch (OutOfMemoryError e) { rotatedBitmap = Bitmap.createBitmap(roughBitmap, 0, 0, roughBitmap.getWidth()/2, roughBitmap.getHeight()/2, m, true); } } if (rotate) { Utils.log(TAG, "Rotate Invoked :------->"); int temp = inHeight; inHeight = inWidth; inWidth = temp; } options.inSampleSize = Math.round(factor); float dstWidth = (int) inWidth / factor; float dstHeight = (int) inHeight / factor; Bitmap resizedBitmap; if (rotate) { try { resizedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) dstWidth, (int) dstHeight, true); } catch (OutOfMemoryError e) { resizedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) dstWidth/2, (int) dstHeight/2, true); } } else { try { resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) dstWidth, (int) dstHeight, true); } catch (OutOfMemoryError e) { resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) dstWidth/2, (int) dstHeight/2, true); } } try { FileOutputStream out = new FileOutputStream(pathOfOutputImage); resizedBitmap.compress(Bitmap.CompressFormat.PNG, 80, out); } catch (Exception e) { Utils.log("Image", e.getMessage() + e); } //Free up the memory. roughBitmap.recycle(); resizedBitmap.recycle(); if (rotatedBitmap != null) { rotatedBitmap.recycle(); } } catch (IOException e) { Utils.log("Image", e.getMessage() + e); } } private static Bitmap fetchRoughBitmap(String pathOfInputImage, float factor) { Bitmap roughBitmap = null; try { FileInputStream in = new FileInputStream(pathOfInputImage); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = Math.round(factor); roughBitmap = BitmapFactory.decodeStream(in, null, options); return roughBitmap; } catch (OutOfMemoryError mem_error) { return Utils.fetchRoughBitmap(pathOfInputImage, factor+1); } catch (FileNotFoundException e) { //return Utils.fetchRoughBitmap(pathOfInputImage, factor+1); return roughBitmap; } } 

Este código funciona bien porque lo ejecuto a través de un bucle recursivo hasta que no se quede sin memoria, pero mi imagen resultante es sólo unos 300 x 300 px y lo necesito para ser de al menos 640×480. Mis preguntas son:

  1. ¿Puede alguien decirme por qué Galaxy S3 utiliza hasta hasta el 90% de memoria cuando carga por primera vez mi aplicación en lugar de 60% en los teléfonos HTC.
  2. ¿Hay algo mal que se hace en el código de re-tamaño que está haciendo que mi aplicación se queda sin memoria.

Cualquier ayuda será muy apreciada ya que ya he pasado 3 días en este tema :-(.

umm … Sé que es una vieja pregunta ahora, pero aquí está lo que pienso.

Galaxy S3 utiliza la densidad xhdpi, por lo tanto, asigna un tamaño de montón más grande en el lanzamiento, (por lo que sé, 32 MB)

pero si no tiene ningún recurso xhdpi en su directorio res, entonces llamará a cualquier imagen predeterminada en drawable o de hdpi que es la más cercana a xhdpi densidad.

A continuación, se ampliará la imagen para ajustarse a sus neeeds, y en esta fase de expansión de la imagen ocupará mucho la memoria, (podría), resultando en problemas de memoria.

Puedes solucionar este problema activando el Modo de compatibilidad de pantalla o simplemente crear (si no hay por defecto) drawable-xhdpi, proporcionando Recursos Apropiados para dispositivos xhdpi como Galaxy S3.

Guau. Hemos luchado con este tema de memoria en el S3 durante semanas. Finalmente, aplicamos una de las técnicas en este hilo.

En nuestra aplicación, teníamos drawable-hdpi tenemos todas las imágenes para la aplicación. En la mayoría de los teléfonos, no tuvimos ningún problema. En el S3, la aplicación tardaría 2 veces más memoria y luego ejecutar en el problema de memoria.

Acabo de crear la carpeta drawable-xhdpi con el mismo contenido que la carpeta drawable-hdpi y la corrí en S3. Inmediatamente notó que la huella de memoria era 1/2 y no hay problemas de memoria.

Esta fue una experiencia frustrante. Ojalá otras personas sepan buscar este hilo y ahorrar horas de degugging.

Gracias

Yo solucioné el problema yo mismo. La aplicación que se queda sin memoria no tiene que hacer nada con el código anterior. Añadí el MAT y vi que los objetos de mapa de bits se mantenían vivos desde vistas anteriores. Así que eliminé los gráficos de la vista y resolvió el problema de memoria.

 I overwrote the onDestroy method and added the following line: layout.setBackgroundDrawable(null);. Please let me know if this worked or didn't work for you. 

– user881148

Cool, funcionó para mí … con un poco añadido para fotos de fondo en un diseño. En lugar de utilizar BitmapDrawables o Bitmap, utilizo Drawables después de convertir de mapa de bits.

 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.outerspace); Drawable bitDraw = new BitmapDrawable(getResources(), bitmap); main.setBackgroundDrawable(bitDraw); 

Mi problema era que estaba trabajando en todos los dispositivos esperan para el S3 (que era molesto). Pero la aplicación está en marcha y funcionando ahora! Gracias … user881148

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.