0

i'm trying to make a wallpaper set app using ImageView. I know its hard to display a bunch of images (especially when images are 1920x1080), what i did was to make other bunch of images with a smaller resolution (400x200) that would be displayed in the app, but when user is trying to set a image as wallpaper it gets the same image but with the bigger resolution. I thought this will solve my problem, but it didn't, the app runs more time then before, but at a moment it fails. I noticed that the app fails after i set 3 images as wallpaper. I try'd to use garbage collector, it doesn't work. Any ideas?

Here is my code.

package app.technozed.winterwallpapers;

import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
import android.app.WallpaperManager;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

ImageView display;
int toPhone;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    toPhone = R.drawable.wal1;

    display = (ImageView) findViewById(R.id.WPdisplay);
    ImageView image1 = (ImageView) findViewById(R.id.WPimg1);
    ImageView image2 = (ImageView) findViewById(R.id.WPimg2);
    ImageView image3 = (ImageView) findViewById(R.id.WPimg3);
    ImageView image4 = (ImageView) findViewById(R.id.WPimg4);
    ImageView image5 = (ImageView) findViewById(R.id.WPimg5);
    ImageView image6 = (ImageView) findViewById(R.id.WPimg6);
    ImageView image7 = (ImageView) findViewById(R.id.WPimg7);
    ImageView image8 = (ImageView) findViewById(R.id.WPimg8);
    ImageView image9 = (ImageView) findViewById(R.id.WPimg9);
    ImageView image10 = (ImageView) findViewById(R.id.WPimg10);
    ImageView image11 = (ImageView) findViewById(R.id.WPimg11);
    ImageView image12 = (ImageView) findViewById(R.id.WPimg12);
    ImageView image13 = (ImageView) findViewById(R.id.WPimg13);
    ImageView image14 = (ImageView) findViewById(R.id.WPimg14);
    ImageView image15 = (ImageView) findViewById(R.id.WPimg15);
    ImageView image16 = (ImageView) findViewById(R.id.WPimg16);
    ImageView image17 = (ImageView) findViewById(R.id.WPimg17);
    ImageView image18 = (ImageView) findViewById(R.id.WPimg18);
    ImageView image19 = (ImageView) findViewById(R.id.WPimg19);
    ImageView image20 = (ImageView) findViewById(R.id.WPimg20);
    ImageView image21 = (ImageView) findViewById(R.id.WPimg21);
    ImageView image22 = (ImageView) findViewById(R.id.WPimg22);
    ImageView image23 = (ImageView) findViewById(R.id.WPimg23);
    ImageView image24 = (ImageView) findViewById(R.id.WPimg24);
    ImageView image25 = (ImageView) findViewById(R.id.WPimg25);
    ImageView image26 = (ImageView) findViewById(R.id.WPimg26);
    ImageView image27 = (ImageView) findViewById(R.id.WPimg27);
    ImageView image28 = (ImageView) findViewById(R.id.WPimg28);
    ImageView image29 = (ImageView) findViewById(R.id.WPimg29);
    ImageView image30 = (ImageView) findViewById(R.id.WPimg30);
    Button setWall = (Button) findViewById(R.id.BsetWall);
    image1.setOnClickListener(this);
    image2.setOnClickListener(this);
    image3.setOnClickListener(this);
    image4.setOnClickListener(this);
    image5.setOnClickListener(this);
    image6.setOnClickListener(this);
    image7.setOnClickListener(this);
    image8.setOnClickListener(this);
    image9.setOnClickListener(this);
    image10.setOnClickListener(this);
    image11.setOnClickListener(this);
    image12.setOnClickListener(this);
    image13.setOnClickListener(this);
    image14.setOnClickListener(this);
    image15.setOnClickListener(this);
    image16.setOnClickListener(this);
    image17.setOnClickListener(this);
    image18.setOnClickListener(this);
    image19.setOnClickListener(this);
    image20.setOnClickListener(this);
    image21.setOnClickListener(this);
    image22.setOnClickListener(this);
    image23.setOnClickListener(this);
    image24.setOnClickListener(this);
    image25.setOnClickListener(this);
    image26.setOnClickListener(this);
    image27.setOnClickListener(this);
    image28.setOnClickListener(this);
    image29.setOnClickListener(this);
    image30.setOnClickListener(this);
    setWall.setOnClickListener(this);
    }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}


@Override
public void onClick(View v) {
    switch (v.getId()){
    case R.id.WPimg1:
         display.setImageResource(R.drawable.wal1);
         toPhone = R.drawable.wal1;
         break;
    case R.id.WPimg2:
         display.setImageResource(R.drawable.wal2);
         toPhone = R.drawable.wal2;
         break;
    case R.id.WPimg3:
         display.setImageResource(R.drawable.wal3);
         toPhone = R.drawable.wal3;
         break;
    case R.id.WPimg4:
         display.setImageResource(R.drawable.wal4);
         toPhone = R.drawable.wal4;
         break;
    case R.id.WPimg5:
         display.setImageResource(R.drawable.wal5);
         toPhone = R.drawable.wal5;
         break;
    case R.id.WPimg6:
         display.setImageResource(R.drawable.wal6);
         toPhone = R.drawable.wal6;
         break;
    case R.id.WPimg7:
         display.setImageResource(R.drawable.wal7);
         toPhone = R.drawable.wal7;
         break;
    case R.id.WPimg8:
         display.setImageResource(R.drawable.wal8);
         toPhone = R.drawable.wal8;
         break;
    case R.id.WPimg9:
         display.setImageResource(R.drawable.wal9);
         toPhone = R.drawable.wal9;;
         break;
    case R.id.WPimg10:
         display.setImageResource(R.drawable.wal10);
         toPhone = R.drawable.wal10;
         break;
    case R.id.WPimg11:
         display.setImageResource(R.drawable.wal11);
         toPhone = R.drawable.wal11;
         break;
    case R.id.WPimg12:
         display.setImageResource(R.drawable.wal12);
         toPhone = R.drawable.wal12;
         break;
    case R.id.WPimg13:
         display.setImageResource(R.drawable.wal13);
         toPhone = R.drawable.wal13;
         break;
    case R.id.WPimg14:
         display.setImageResource(R.drawable.wal14);
         toPhone = R.drawable.wal14;
         break;
    case R.id.WPimg15:
         display.setImageResource(R.drawable.wal15);
         toPhone = R.drawable.wal15;
         break;
    case R.id.WPimg16:
         display.setImageResource(R.drawable.wal16);
         toPhone = R.drawable.wal16;
         break;
    case R.id.WPimg17:
         display.setImageResource(R.drawable.wal17);
         toPhone = R.drawable.wal17;
         break;
    case R.id.WPimg18:
         display.setImageResource(R.drawable.wal18);
         toPhone = R.drawable.wal18;
         break;
    case R.id.WPimg19:
         display.setImageResource(R.drawable.wal19);
         toPhone = R.drawable.wal19;
         break;
    case R.id.WPimg20:
         display.setImageResource(R.drawable.wal20);
         toPhone = R.drawable.wal20;
         break;
    case R.id.WPimg21:
         display.setImageResource(R.drawable.wal21);
         toPhone = R.drawable.wal21;
         break;
    case R.id.WPimg22:
         display.setImageResource(R.drawable.wal22);
         toPhone = R.drawable.wal22;
         break;
    case R.id.WPimg23:
         display.setImageResource(R.drawable.wal23);
         toPhone = R.drawable.wal23;
         break;
    case R.id.WPimg24:
         display.setImageResource(R.drawable.wal24);
         toPhone = R.drawable.wal24;
         break;
    case R.id.WPimg25:
         display.setImageResource(R.drawable.wal25);
         toPhone = R.drawable.wal25;
         break;
    case R.id.WPimg26:
         display.setImageResource(R.drawable.wal26);
         toPhone = R.drawable.wal26;
         break;
    case R.id.WPimg27:
         display.setImageResource(R.drawable.wal27);
         toPhone = R.drawable.wal27;
         break;
    case R.id.WPimg28:
         display.setImageResource(R.drawable.wal28);
         toPhone = R.drawable.wal28;
         break;
    case R.id.WPimg29:
         display.setImageResource(R.drawable.wal29);
         toPhone = R.drawable.wal29;
         break;
    case R.id.WPimg30:
         display.setImageResource(R.drawable.wal30);
         toPhone = R.drawable.wal30;
         break;
    case R.id.BsetWall:
         try{
                  WallpaperManager.getInstance(getApplicationContext()).setResource(toPhone);
             Toast.makeText(getApplicationContext(), "Wallpaper was set!", Toast.LENGTH_SHORT).show();
         } catch(IOException e) {
             e.printStackTrace();
             Toast.makeText(getApplicationContext(), "No privileges!", Toast.LENGTH_SHORT).show();
         }
         break;
    }

    }

    }

And here is the LogCat.

--- allocation failed for scaled bitmap
Shutting down VM
threadid=1: thread exiting with uncaught exception (group=0x41618ba8)
FATAL EXCEPTION: main
Process: app.technozed.winterwallpapers, PID: 2574
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:587)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:422)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:840)
at android.content.res.Resources.loadDrawable(Resources.java:2110)
at android.content.res.Resources.getDrawable(Resources.java:700)
at android.widget.ImageView.resolveUri(ImageView.java:638)
at android.widget.ImageView.setImageResource(ImageView.java:367)
at app.technozed.winterwallpapers.MainActivity.onClick(MainActivity.java:143)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
11
  • possible duplicate of Out of Memory error with Bitmap Commented Dec 28, 2013 at 17:37
  • i'm not using Bitmap. Commented Dec 28, 2013 at 17:38
  • well basic issue your image is big and need to be scaled down. also so many imageviews. something to consider for design change Commented Dec 28, 2013 at 17:39
  • what folder are the images stored in? Commented Dec 28, 2013 at 17:41
  • @KickAss drawable-hdpi Commented Dec 28, 2013 at 17:44

2 Answers 2

8

Move the images to a new folder called "drawable-nodpi".

Reason

Images in different drawable folders are opened by the android system with different memory allocations, hdpi means it will take a LOT of memory even if the image is tiny.

drawable-nodpi is the best for memory saving.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I had to filter through a lot of SO answers to find this. I put my images into xxhdpi and problem went away.
you are a life saver
@David I don't understand how your problem is solved by adding the images in xxhdpi, isn't this against the accepted answer, where in folder as xxhdpi mean it will take a lot of memory?
@KickAss Thank you so much, I tested it using Memory Monitor in Android Studio, let's just say that such info should be "Fixed Tipped" on the front page of Google / Android / Android Studio application, down from 110MB to load 5 jpeg images (700x400) inside drawable folder, to about 40MB when I added it inside "drawable-nodpi" folder.
2

To fix OutOfMemory you should do something like that:

BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap=BitmapFactory.decodeStream(is,null,options);

This inSampleSize option reduces memory consumption.

Here's a complete method. First it reads image size without decoding the content itself. Then it finds the best inSampleSize value, it should be a power of 2. And finally the image is decoded.

//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
    //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f),null,o);

    //The new size we want to scale to
    final int REQUIRED_SIZE=70;

    //Find the correct scale value. It should be the power of 2.
    int scale=1;
    while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
        scale*=2;

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize=scale;
    return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.