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)
George Lungu
  • 125
  • 2
  • 4
  • 16

2 Answers2

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.

KickAss
  • 4,210
  • 8
  • 33
  • 41
  • 2
    Thanks. I had to filter through a lot of SO answers to find this. I put my images into xxhdpi and problem went away. – David Jul 29 '15 at 22:52
  • you are a life saver – Remon Amin Feb 13 '16 at 01:22
  • @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? – Ashraf Alshahawy Apr 17 '16 at 03:46
  • 1
    @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. – Ashraf Alshahawy Apr 17 '16 at 03:59
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;
}
Shirish Herwade
  • 11,461
  • 20
  • 72
  • 111