Android : Android GoogleMap.snapshot(GoogleMap.SnapshotReadyCallback callback) crash on low memory

on Friday, July 4, 2014


My question is : Is this considered a bug, or should you make sure that you are not low on memory before calling this function ?


What would be the expected behavior ?


Even with a memory leak, if failing to allocate a Bitmap, the snapshot function should just return a null Bitmap instead of crashing the app.


Since it is hard to simulate low memory, I created a memory leak to demonstrate the problem.



  1. create a crashSnapshot() function with a call to the GoogleMap.snapshot (GoogleMap.SnapshotReadyCallback callback) function

  2. have the SnapshotReadyCallback add the created bitmap to a list

  3. call crash() several times => it will end up crashing


The code :



private final GoogleMap map;
public final List<Bitmap> memoryLeak = new ArrayList<Bitmap>();
public void crashSnapshot() {
map.snapshot(new SnapshotReadyCallback() {
@Override
public void onSnapshotReady(final Bitmap _bitmap) {
memoryLeak.add(_bitmap);
}
});
}


The exception logs :



"Thread-69611" prio=5 tid=26 RUNNABLE
| group="main" sCount=0 dsCount=0 obj=0x427ebe98 self=0x5bb0b048
| sysTid=7522 nice=0 sched=0/0 cgrp=apps handle=1535913752
| state=R schedstat=( 85730418 2522207 12 ) utm=7 stm=1 core=2
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
at android.graphics.Bitmap.createBitmap(Bitmap.java:670)
at ovh.a((null):-1)
at oyn.run((null):-1)
at java.lang.Thread.run(Thread.java:841)
threadid=26: thread exiting with uncaught exception (group=0x41d8b700)
FATAL EXCEPTION: Thread-69611
java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
at android.graphics.Bitmap.createBitmap(Bitmap.java:670)
at ovh.a(Unknown Source)
at oyn.run(Unknown Source)
at java.lang.Thread.run(Thread.java:841)


Also, you can pre-allocate the bitmap and pass it on to the snapshot function, thus handling allocation exceptions yourself, but it is not garanteed that another bitmap is not going to be allocated anyways. The javadoc of snapshot (GoogleMap.SnapshotReadyCallback callback, Bitmap bitmap) says



Although in most cases the object passed by the callback method is the same as the one given in the parameter to this method, in some cases the returned object can be different (e.g., if the view's dimensions have changed by the time the snapshot is actually taken). Thus, you should only trust the content of the bitmap passed by the callback method.



0 comments:

Post a Comment