10

This is in connection with this question:

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)

I created the dump file in question, and it gives the following information:

One instance of "byte[]" loaded by "<system class loader>" occupies 1,10,59,216
(51.02%) bytes. The memory is accumulated in one instance of "byte[]" 
 loaded by "<system class loader>".

Keywords byte[]

So now what can be done? How do I clear the problem?

My list_objects[context]-inbound file:

CLASS NAME                                                                 SHALLOW HEAP   RETAINED HEAP  
byte[11059200] @ 0xb4979590                                               |  1,10,59,216 |   1,10,59,216
mBuffer android.graphics.Bitmap @ 0xb3dc68d8                              |48            | 48
mBitmap android.graphics.drawable.BitmapDrawable @ 0xb3dbba60             | 72           | 144
mBackground android.widget.RelativeLayout @ 0xb3db3fc0                    |512           | 10,144
mBitmap android.graphics.drawable.BitmapDrawable$BitmapState @ 0xb3dc0068 |40          | 40
mBitmapState android.graphics.drawable.BitmapDrawable @ 0xb3dbba60        |72          |  144
referent java.lang.ref.WeakReference @ 0xb3dc2d68                         |24          |  24

How can I solve the memory problem?

My home_screen.java

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.home_page);
    main();
 private void main() {
    // TODO Auto-generated method stub
    
    
    final Button home;
    final Button aboutus;
    final Button contacts;
    final Button clients;
    final Button services;
    
    try
    {

    home = (Button)findViewById(R.id.btnHome);
    aboutus = (Button)findViewById(R.id.btnAboutus);
    clients = (Button)findViewById(R.id.btnClients);
    contacts = (Button)findViewById(R.id.btnContacts);
    services = (Button)findViewById(R.id.btnServices);
    
    home.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.home1);
            Drawable d = new BitmapDrawable(getResources(),b);              
            home.setBackgroundDrawable(d);
            System.gc();
            Intent myIntent = new Intent(Home_Screen.this, Button_Anime.class);
            startActivity(myIntent);
        }
    });
    aboutus.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.about1 );
            Drawable d = new BitmapDrawable(getResources(),b); 
            aboutus.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, AboutUs.class);
            startActivity(myIntent);
        }
    });
    clients.setOnClickListener(new  OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.clients1 );
            Drawable d = new BitmapDrawable(getResources(),b); 
            clients.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Clients.class);
            startActivity(myIntent);
        }
    });
    contacts.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.contact1);
            Drawable d = new BitmapDrawable(getResources(),b);
            contacts.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Contacts.class);
            startActivity(myIntent);
        }
    });
    services.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.services1 );
            Drawable d = new BitmapDrawable(getResources(),b);
            services.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Services.class);
            startActivity(myIntent);
        }
    });

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}
Patrick Yoder
  • 1,065
  • 4
  • 14
  • 19
user3214173
  • 227
  • 3
  • 14
  • Dude go through [My this Answer](http://stackoverflow.com/questions/24156047/android-binary-xml-exception-when-changing-pictures/24157195#24157195) will help you. – Pankaj Arora Jun 11 '14 at 09:17
  • i have done all this.. and am still getting the same error.. my files are all 30-40kb sizze and yes i have set heap to large @DevCarlsberg – user3214173 Jun 11 '14 at 09:48

4 Answers4

4

The idea is to down sample your image so that it looks good on the smaller screen and that you dont have to load the entire bitmap in memory.

1) First get the size of your ImageView/ screen that you will be displaying on.

2) Read the size of you Bitmap by passing in BitmapFactory.Options.inJustDecodeBounds. This will give you the size of the Bitmap rather than loading the entire bitmap.

3) Get a insample size. Calculate the ratio of height and width of the screen to the image height and width. Use the smallest one so that the biggest dimension looks good.

4) Final use the function below to get the down sampled image that wont eat up your memory.

2)(code)

BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, bitmapOptions);
int imageWidth = bitmapOptions.outWidth;
int imageHeight = bitmapOptions.outHeight;
inputStream.close();

4)(code)

private Bitmap downscaleBitmapUsingDensities(final int sampleSize,final int imageResId)
  {
  final Options bitmapOptions=new Options();
  bitmapOptions.inDensity=sampleSize;
  bitmapOptions.inTargetDensity=1;
  final Bitmap scaledBitmap=BitmapFactory.decodeResource(getResources(),imageResId,bitmapOptions);
  scaledBitmap.setDensity(Bitmap.DENSITY_NONE);
  return scaledBitmap;
  }
toidiu
  • 965
  • 2
  • 12
  • 25
2

Adding largeHeap="true" in your manifest may help. This will allow your application to use more memory.

See: http://developer.android.com/guide/topics/manifest/application-element.html

clemp6r
  • 3,665
  • 2
  • 26
  • 31
  • This is a bandaid at best, from the link: "Most apps should not need this and should instead focus on reducing their overall memory usage." – Sully Apr 16 '15 at 17:44
1

try the below code:

Resources res = getContext().getResources();
int id = R.drawable.image; 
Bitmap b = BitmapFactory.decodeResource(res, id);    
_img .setimagebitmap(b);
Pankaj Arora
  • 10,224
  • 2
  • 37
  • 59
  • @DevCalsberg this code dosn't work eclipse dosnt accept it.. Resources res = getContext().getResources(); home.setimagebitmap(b); both these codes produce error.. and also isnt this code logically the same as what i used??? – user3214173 Jun 11 '14 at 10:12
1

Normally when i get this kind of exception on low Ram devices it's because i have some kind of image to expensive (many kb) for this resolution. I had a weird problem because i just used xhdpi and hdpi drawables directories, on mdpi or even ldpi devices the hdpi conversion to the right resolution raise this exception because cannot resize the image.

It's happens on any device? Could you check you have a specific graphics for this low devices?

Any way with HPOF file you can see what kind of object or at least, wich activity/view has the problem. You need to analyze all this data (there is no a master plan to find the resource it's collapsing your app) to see which has the problem.

Hope this helps, any question, please feel free to ask.

Sulfkain
  • 5,082
  • 1
  • 20
  • 38