studio programacion permission permisos móviles internet example editar desarrollo curso aplicaciones androidmanifest android memory heap heap-memory

programacion - permisos android manifest



Detecta el tamaño del montón de aplicaciones en Android (9)

¿Cómo se detecta mediante programación el tamaño del montón de aplicaciones disponible para una aplicación de Android?

Escuché que hay una función que hace esto en versiones posteriores del SDK. En cualquier caso, estoy buscando una solución que funcione para 1.5 y hacia arriba.


¿Te refieres a programáticamente, o simplemente mientras estás desarrollando y depurando? Si es este último, puede ver esa información desde la perspectiva de DDMS en Eclipse. Cuando su emulador (posiblemente incluso el teléfono físico que está conectado) se está ejecutando, mostrará una lista de los procesos activos en una ventana a la izquierda. Puede seleccionarlo y hay una opción para rastrear las asignaciones de montón.


Algunas operaciones son más rápidas que el administrador de espacio de Java Heap. Retrasar las operaciones por un tiempo puede liberar espacio en la memoria. Puede usar este método para escapar del error de tamaño de pila:

waitForGarbageCollector(new Runnable() { @Override public void run() { // Your operations. } }); /** * Measure used memory and give garbage collector time to free up some * space. * * @param callback Callback operations to be done when memory is free. */ public static void waitForGarbageCollector(final Runnable callback) { Runtime runtime; long maxMemory; long usedMemory; double availableMemoryPercentage = 1.0; final double MIN_AVAILABLE_MEMORY_PERCENTAGE = 0.1; final int DELAY_TIME = 5 * 1000; runtime = Runtime.getRuntime(); maxMemory = runtime.maxMemory(); usedMemory = runtime.totalMemory() - runtime.freeMemory(); availableMemoryPercentage = 1 - (double) usedMemory / maxMemory; if (availableMemoryPercentage < MIN_AVAILABLE_MEMORY_PERCENTAGE) { try { Thread.sleep(DELAY_TIME); } catch (InterruptedException e) { e.printStackTrace(); } waitForGarbageCollector( callback); } else { // Memory resources are availavle, go to next operation: callback.run(); } }


Así es como lo haces:

Obteniendo el tamaño máximo de almacenamiento dinámico que la aplicación puede usar:

Runtime runtime = Runtime.getRuntime(); long maxMemory=runtime.maxMemory();

Cómo obtener la mayor parte del montón que usa actualmente su aplicación:

long usedMemory=runtime.totalMemory() - runtime.freeMemory();

Cómo obtener la mayor parte del montón que su aplicación puede usar ahora (memoria disponible):

long availableMemory=maxMemory-usedMemory;

Y, para formatear cada uno de ellos muy bien, puede usar:

String formattedMemorySize=Formatter.formatShortFileSize(context,memorySize);


Asus Nexus 7 (2013) 32Gig: getMemoryClass () = 192 maxMemory () = 201326592

Cometí el error de crear un prototipo de mi juego en el Nexus 7, y luego descubrí que se había quedado sin memoria casi de inmediato en la tableta genérica 4.04 de mi esposa (clase de memoria 48, maxmemory 50331648)

Tendré que reestructurar mi proyecto para cargar menos recursos cuando determine que la clase de memoria es baja.
¿Hay alguna forma en Java para ver el tamaño del montón actual? (Puedo verlo claramente en el logCat cuando se depura, pero me gustaría una forma de verlo en el código para adaptarlo, como si currentheap> (maxmemory / 2) descargara mapas de bits de alta calidad carga baja calidad


Esto devuelve el tamaño máximo de almacenamiento dinámico en bytes:

Runtime.getRuntime().maxMemory()

Estaba usando ActivityManager.getMemoryClass () pero en CyanogenMod 7 (no lo probé en otro sitio) devuelve un valor incorrecto si el usuario establece el tamaño del montón manualmente.


Hay dos formas de pensar sobre su frase "tamaño de pila de aplicaciones disponible":

  1. ¿Cuánto montón puede usar mi aplicación antes de que se active un error? Y

  2. ¿Cuánta pila debería usar mi aplicación, dadas las limitaciones de la versión del sistema operativo Android y el hardware del dispositivo del usuario?

Hay un método diferente para determinar cada uno de los anteriores.

Para el artículo 1 anterior: maxMemory()

que se puede invocar (por ejemplo, en el método onCreate() su actividad principal) de la siguiente manera:

Runtime rt = Runtime.getRuntime(); long maxMemory = rt.maxMemory(); Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));

Este método le dice cuántos bytes totales de pila puede usar su aplicación.

Para el artículo 2 anterior: getMemoryClass()

que se puede invocar de la siguiente manera:

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); int memoryClass = am.getMemoryClass(); Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));

Este método le informa aproximadamente cuántos megabytes de pila debe usar su aplicación si quiere respetar debidamente los límites del presente dispositivo y los derechos de otras aplicaciones para ejecutarse sin ser forzados repetidamente en el onStop() / onResume() ciclo, ya que son borrados groseramente de la memoria mientras su aplicación elefantina toma un baño en el jacuzzi Android.

Esta distinción no está claramente documentada, hasta donde sé, pero he probado esta hipótesis en cinco dispositivos Android diferentes (ver a continuación) y he confirmado, a mi entera satisfacción, que esta es una interpretación correcta.

Para una versión maxMemory() de Android, maxMemory() típicamente devolverá la misma cantidad de megabytes que se indican en getMemoryClass() (es decir, aproximadamente un millón de veces el último valor).

La única situación (de la que soy consciente) para la cual los dos métodos pueden divergir es en un dispositivo rooteado que ejecuta una versión de Android como CyanogenMod, que permite al usuario seleccionar de forma manual qué tamaño de heap debe permitirse para cada aplicación. En CM, por ejemplo, esta opción aparece en "Configuración de CyanogenMod" / "Rendimiento" / "Tamaño de almacenamiento dinámico de VM".

NOTA: TENGA EN CUENTA QUE CONFIGURAR ESTE VALOR MANUALMENTE PUEDE ARRASTRAR SU SISTEMA, ESPECIALMENTE si selecciona un valor inferior al normal para su dispositivo.

Estos son los resultados de mi prueba que muestran los valores devueltos por maxMemory() y getMemoryClass() para cuatro dispositivos diferentes que ejecutan CyanogenMod, utilizando dos valores de montón diferentes (configurados manualmente) para cada uno:

  • G1:
    • Con VM Heap Size configurado en 16 MB:
      • maxMemory: 16777216
      • getMemoryClass: 16
    • Con VM Heap Size establecido en 24MB:
      • maxMemory: 25165824
      • getMemoryClass: 16
  • Moto Droid:
    • Con VM Heap Size establecido en 24MB:
      • maxMemory: 25165824
      • getMemoryClass: 24
    • Con VM Heap Size configurado en 16 MB:
      • maxMemory: 16777216
      • getMemoryClass: 24
  • Nexus One:
    • Con VM Heap size establecido en 32MB:
      • maxMemory: 33554432
      • getMemoryClass: 32
    • Con VM Heap size establecido en 24MB:
      • maxMemory: 25165824
      • getMemoryClass: 32
  • Viewsonic GTab:
    • Con VM Heap Size establecido en 32:
      • maxMemory: 33554432
      • getMemoryClass: 32
    • Con VM Heap Size establecido en 64:
      • maxMemory: 67108864
      • getMemoryClass: 32

Además de lo anterior, probé en una tableta Novo7 Paladin con Ice Cream Sandwich. Esta fue esencialmente una versión original de ICS, excepto que he rooteado la tableta a través de un proceso simple que no reemplaza todo el sistema operativo y, en particular, no proporciona una interfaz que permita ajustar manualmente el tamaño del almacenamiento dinámico.

Para ese dispositivo, aquí están los resultados:

  • Novo7
    • maxMemory: 62914560
    • getMemoryClass: 60

También (por Kishore en un comentario a continuación):

  • HTC uno X
    • maxMemory: 67108864
    • getMemoryClass: 64

Y (por el comentario de akauppi):

  • Samsung Galaxy Core Plus
    • maxMemory: (no especificado en el comentario)
    • getMemoryClass: 48
    • largeMemoryClass: 128

Por un comentario de cmcromance:

  • Gran montón de Galaxy S3 (Jelly Bean)
    • maxMemory: 268435456
    • getMemoryClass: 64

Y (por comentarios de tencent):

  • LG Nexus 5 (4.4.3) normal
    • maxMemory: 201326592
    • getMemoryClass: 192
  • LG Nexus 5 (4.4.3) gran cantidad
    • maxMemory: 536870912
    • getMemoryClass: 192
  • Galaxy Nexus (4.3) normal
    • maxMemory: 100663296
    • getMemoryClass: 96
  • Galaxy Nexus (4.3) gran cantidad
    • maxMemory: 268435456
    • getMemoryClass: 96
  • Galaxy S4 Play Store Edition (4.4.2) normal
    • maxMemory: 201326592
    • getMemoryClass: 192
  • Galaxy S4 Play Store Edition (4.4.2) gran montón
    • maxMemory: 536870912
    • getMemoryClass: 192

Otros dispositivos

  • Huawei Nexus 6P (6.0.1) normal
    • maxMemory: 201326592
    • getMemoryClass: 192

No he probado estos dos métodos utilizando la opción de manifiesto android: largeHeap = "true" disponible desde Honeycomb, pero gracias a cmcromance y tencent tenemos algunos valores grandes de SampleHeap, como se informó anteriormente.

Mi expectativa (que parece ser respaldada por los números de HEPA grandes arriba) sería que esta opción tendría un efecto similar a establecer el montón manualmente a través de un SO rooteado, es decir, aumentaría el valor de maxMemory() mientras dejaba getMemoryClass() solo. Hay otro método, getLargeMemoryClass (), que indica la cantidad de memoria permitida para una aplicación que utiliza la configuración de gran tamaño. La documentación de getLargeMemoryClass () indica que "la mayoría de las aplicaciones no deberían necesitar esta cantidad de memoria y, en su lugar, deberían permanecer con el límite getMemoryClass ()".

Si lo he adivinado correctamente, usar esa opción tendría los mismos beneficios (y riesgos) que usar el espacio disponible por un usuario que ha subido el montón a través de un SO rooteado (es decir, si su aplicación usa la memoria adicional, probablemente no funcionará tan bien con cualquier otra aplicación que el usuario esté ejecutando al mismo tiempo).

Tenga en cuenta que la clase de memoria aparentemente no necesita ser un múltiplo de 8 MB.

Podemos ver a partir de lo anterior que el resultado de getMemoryClass() cambia para una configuración determinada de dispositivo / sistema operativo, mientras que el valor de maxMemory () cambia cuando el usuario establece el montón de forma diferente.

Mi propia experiencia práctica es que en el G1 (que tiene una clase de memoria de 16), si selecciono manualmente 24 MB como el tamaño del almacenamiento dinámico, puedo ejecutar sin error incluso cuando el uso de la memoria puede descender hasta 20 MB (es de suponer que podría ir tan alto como 24 MB, aunque no he probado esto). Pero otras aplicaciones similarmente grandes pueden borrarse de la memoria como resultado de la locura de mi propia aplicación. Y, a la inversa, mi aplicación puede borrarse de la memoria si el usuario pone estas aplicaciones de alto mantenimiento en primer plano.

Por lo tanto, no puede maxMemory() la cantidad de memoria especificada por maxMemory() . Y, debe intentar mantenerse dentro de los límites especificados por getMemoryClass() . Una forma de hacerlo, si todo lo demás falla, podría ser limitar la funcionalidad de dichos dispositivos de una manera que conserve la memoria.

Finalmente, si planeas pasar la cantidad de megabytes especificada en getMemoryClass() , mi consejo sería trabajar arduamente para salvar y restaurar el estado de tu aplicación, de modo que la experiencia del usuario sea prácticamente ininterrumpida si onStop() / onResume() se produce el ciclo.

En mi caso, por razones de rendimiento, estoy limitando mi aplicación a dispositivos con 2.2 o superior, y eso significa que casi todos los dispositivos que ejecutan mi aplicación tendrán una clase de memoria de 24 o superior. Así que puedo diseñar para ocupar hasta 20 MB de capacidad y me siento bastante seguro de que mi aplicación funcionará bien con las otras aplicaciones que el usuario puede estar ejecutando al mismo tiempo.

Pero siempre habrá unos pocos usuarios rooteados que hayan cargado una versión 2.2 o superior de Android en un dispositivo anterior (por ejemplo, un G1). Cuando se encuentre con una configuración de este tipo, idealmente, debería reducir el uso de memoria, incluso si maxMemory() le dice que puede ir mucho más allá de los 16 MB que getMemoryClass() le indica que debería estar orientando. Y si no puede asegurarse de que su aplicación funcionará dentro de ese presupuesto, al menos asegúrese de que onStop() / onResume() funcione a la perfección.

getMemoryClass() , como lo indica Diane Hackborn (hackbod), solo está disponible para API nivel 5 (Android 2.0), por lo que, como ella aconseja, puede suponer que el hardware físico de cualquier dispositivo que ejecute una versión anterior del El sistema operativo está diseñado para admitir de manera óptima aplicaciones que ocupan un espacio de almacenamiento dinámico de no más de 16 MB.

Por el contrario, maxMemory() , de acuerdo con la documentación, está disponible desde el nivel 1 de API. maxMemory() , en una versión anterior a la 2.0, probablemente devolverá un valor de 16MB, pero veo eso en mi (mucho más tarde) las versiones de CyanogenMod el usuario puede seleccionar un valor de almacenamiento tan bajo como 12 MB, lo que presumiblemente resultaría en un límite de maxMemory() dinámico más bajo, por lo que le sugiero que continúe probando el valor de maxMemory() , incluso para versiones del sistema operativo antes de 2.0. Incluso puede que tenga que negarse a ejecutar en el improbable caso de que este valor sea inferior a 16 MB, si necesita tener más de lo que maxMemory() indica está permitido.


La API oficial es:

Esto fue introducido en 2.0 donde aparecieron dispositivos de memoria más grandes. Puede suponer que los dispositivos que ejecutan versiones anteriores del sistema operativo están utilizando la clase de memoria original (16).


Debug.getNativeHeapSize() hará el truco, creo. Sin embargo, ha estado allí desde 1.0.

La clase Debug tiene muchos métodos excelentes para rastrear asignaciones y otras preocupaciones de rendimiento. Además, si necesita detectar una situación de poca memoria, consulte Activity.onLowMemory() .


Runtime rt = Runtime.getRuntime(); rt.maxMemory()

el valor es b

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); am.getMemoryClass()

valor es MB