[Tenga en cuenta que (como dice CommonsWare señala a continuación) todo el enfoque en esta respuesta solo aplica hasta 2.3.x (Gingerbread) inclusive. A partir de Honeycomb, los datos de mapa de bits se asignan en el montón de VM.]
Los datos de mapa de bits no se asignan en el montón de VM. Hay una referencia en el montón de VM (que es pequeño), pero la biblioteca subyacente de Skia asigna los datos reales en el montón nativo.
Lamentablemente, si bien la definición de BitmapFactory.decode ...() dice que devuelve null si no se ha podido descodificar los datos de la imagen, la implementación Skia (o más bien el pegamento JNI entre el código Java y Skia) registra el mensaje que está viendo ("VM no nos permitirá asignar xxxx bytes") y luego lanza una excepción OutOfMemory con el mensaje engañoso "el tamaño del mapa de bits excede el presupuesto de VM".
El problema no está en el montón de VM, sino en el montón nativo. El montón de Native se comparte entre las aplicaciones en ejecución, por lo que la cantidad de espacio libre depende de qué otras aplicaciones se estén ejecutando y del uso de su mapa de bits. Pero, dado que BitmapFactory no volverá, necesita una forma de averiguar si la llamada tendrá éxito antes de hacerlo.
Existen rutinas para supervisar el tamaño del montón nativo (consulte los métodos getNative de la clase Debug). Sin embargo, he encontrado que getNativeHeapFreeSize() y getNativeHeapSize() no son confiables. Entonces, en una de mis aplicaciones que crea dinámicamente una gran cantidad de bitmaps, hago lo siguiente.
El tamaño del montón nativo varía según la plataforma.Por lo tanto, al inicio, verificamos el tamaño máximo de almacenamiento dinámico de máquinas virtuales permitido para determinar el tamaño de almacenamiento dinámico nativo máximo permitido. [Los números mágicos se determinaron mediante ensayos con 2.1 y 2.2, y pueden ser diferentes en otros niveles de la API.]
long mMaxVmHeap = Runtime.getRuntime().maxMemory()/1024;
long mMaxNativeHeap = 16*1024;
if (mMaxVmHeap == 16*1024)
mMaxNativeHeap = 16*1024;
else if (mMaxVmHeap == 24*1024)
mMaxNativeHeap = 24*1024;
else
Log.w(TAG, "Unrecognized VM heap size = " + mMaxVmHeap);
A continuación, cada vez que tenemos que llamar BitmapFactory que preceden a la llamada de un cheque de la forma.
long sizeReqd = bitmapWidth * bitmapHeight * targetBpp/8;
long allocNativeHeap = Debug.getNativeHeapAllocatedSize();
if ((sizeReqd + allocNativeHeap + heapPad) >= mMaxNativeHeap)
{
// Do not call BitmapFactory…
}
Tenga en cuenta que la heapPad es un número mágico para tener en cuenta el hecho de que a) la notificación de tamaño de la pila nativa es "suave" y b) que quiere dejar algo de espacio en el montón nativo para otras aplicaciones. Estamos corriendo con un pad 3 * 1024 * 1024 (es decir, 3Mbytes) actualmente.
[this] (http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object/14731953#14731953) ¡puede ayudar! –