1

I have a Xamarin.Android application who contains a lot of button in her main game activity (25+).

When I press on a button, I randomly get a crash on my application. I have the following logs for the crash :

Xamarin caused by: java.lang.OutOfMemoryError: Failed to allocate a 44236812 byte allocation with 8344256 free bytes and 7MB until OOM
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2228)
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:4211)
    at android.content.res.Resources.loadDrawable(Resources.java:4085)
    at android.content.res.Resources.getDrawable(Resources.java:2005)
    at android.content.res.Resources.getDrawable(Resources.java:1987)
    at android.content.Context.getDrawable(Context.java:464)
    at android.view.View.setBackgroundResource(View.java:18532)
    at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
    at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:29)
    at android.view.View.performClick(View.java:5702)
    at android.widget.TextView.performClick(TextView.java:10888)
    at android.view.View$PerformClick.run(View.java:22541)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:158)
    at android.app.ActivityThread.main(ActivityThread.java:7229)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

I do not know what really happends and how to fix it. An interested fact is that when I install the app, I did not face any issue the first time I use it. If I close the app and restart it, I get random crash on a button click event. The button action is to set a différent background image on a ImageView.

You can find a snapshot of my method who change the background :

private void SetErrorImage(ImageView component, int errorNumber)
{
    switch (errorNumber)
    {
        case 0:
            component.SetBackgroundResource(Resource.Drawable.arbre_00);
            break;
        case 1:
            component.SetBackgroundResource(Resource.Drawable.arbre_01);
            break;
        case 2:
            component.SetBackgroundResource(Resource.Drawable.arbre_02);
            break;
        case 3:
            component.SetBackgroundResource(Resource.Drawable.arbre_03);
            break;
        case 4:
            component.SetBackgroundResource(Resource.Drawable.arbre_04);
            break;
        case 5:
            component.SetBackgroundResource(Resource.Drawable.arbre_05);
            break;
        case 6:
            component.SetBackgroundResource(Resource.Drawable.arbre_06);
            break;
        case 7:
            component.SetBackgroundResource(Resource.Drawable.arbre_07);
            break;
    }
}

Following this link, is it possible to use something like this Java method in Xamarin ?

((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
Community
  • 1
  • 1
Xavier W.
  • 1,270
  • 3
  • 21
  • 47
  • Looks like you're trying to use too much memory. Are you doing some heavy stuff with images? Could you please show the code where this part fails? – Gerald Versluis Jul 06 '16 at 08:19
  • @GeraldVersluis I edit my post and add a sample of code. My button action event goes into this method every time. – Xavier W. Jul 06 '16 at 08:28

2 Answers2

2

Not the reason where your app looses the memory but a way to make OutOfMemoryError less likely.

I see that android wants to allocate "44236812" bytes (44 Megabytes) for an uncompressed image that may come from a 2048*1536 pixel 1.6MB jpg file.

Have you tried to reduce your resource images (less pixels or less bits per pixel)? Is your device capable to display this high resolution?

k3b
  • 14,517
  • 7
  • 53
  • 85
  • 1
    I solved my issue resizing my images. I had 720*960 pixel images and they are now 300*400 pixel. Problem solved. However, I read that it's recommended to have folder like `drawable-mdpi`, `drawable-hdpi`, `drawable-xhdpi`,`drawable-xxhdpi`, but I wonder what resolution can I "put" into each folder. – Xavier W. Jul 06 '16 at 12:35
  • You should watch your memory and check if it keeps steady when you rotate your app or do something that the image gets recreated a bunch of times. You "might" have just reduced the memory issue now by making the image smaller, though you shouldnt use big images anyway. For your question, check https://developer.android.com/guide/practices/screens_support.html out. – Noires Jul 06 '16 at 13:25
0

As you kinda thought, you need to free the images properly. Even just changing the orientation several times, will just allocate more and more memory, if you dont free it properly.

Basically just

imageView.SetImageDrawable(null)

should do the trick.

Noires
  • 643
  • 8
  • 19