I'm currently working on a simple Android game for school, and the game runs for a little bit before it runs out of memory and crashes. I suspect this has to do with the number of images I'm using in the game (small, 10-20 KB sized files for 10+ items/characters/buttons, and also a very large, 450 KB PNG file for a splash screen background).
I've been using BitmapFactory to decode all of my small item PNGs, and I also was able to set the background for my main GameView as so (only the bare minimum of example code is included):
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap background, invincibleBitmap;
//Sets the background bitmap to an image scaled to the same size as the user's screen
background = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background), getWidth(), getHeight(), false);
invincibleBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.invincible_item), 60, 60, false);
For the splash screen I mentioned earlier, however, I've been using the Activity's Layout XML file to set the image as so:
android:background="#drawable/main"
I want to be able to scale main.png the same way that I did in a View in an Activity, hoping that it would help the memory overload problem. How would I go about doing this? I'm a beginner with Android in general so the simpler the solution, the better.
To point out, image file size don't effect memory usage. It depend on the image specs: width x height x 1 byte.
You shouldn't set splash screen image in code by scaling it depending on screen resolution. The drawable folders are there to do that. Provide a different image with different specs for each of the screen resolution categories (l,m,x,xx,xxx).
As a fast solution, copy and paste the same image to all the
drawable folders. Surprisingly you will notice a difference.
Related
I have an Activity where I have a background image in an ImageView, and nine transparent buttons on top of the image.
http://i.stack.imgur.com/GGQqd.png
When I tap any of the buttons I make a RelativeLayout appears in the top of the background.
http://i.stack.imgur.com/JvKQK.jpg
The problem is: When I use a big resolution image as a background in the layout the performance is very poor.
I'm using a PNG image of 2048 x 1536, and it's weight is about 500k.
When I use a smaller image like 1024 x 768 the application works fine, but it looks terrible.
Is there a restriction or a method to use big images without losing performance?
That bitmap is huge. The 500k you mention is the compressed size. Images are uncompressed in memory when you use them. You're actually looking at 2048×1536×4 = 12582912 = over 12MB of memory use.
If you're on a device like Nexus 9 that has that screen resolution, then you can reasonably assume it also has the memory, GPU and bus bandwidth to deal with an image of that size. However, if you're on a lower resolution device (most devices are, keep in mind that even Full HD is just 65% as large), then this image is phenomenally wasteful of memory. You can buy low end devices today with a 240x320 screen, where a full screen bitmap is a mere 2.5% the size of your image.
You're going to have to scale that image when you load it. Use BitmapFactory.Options to set the desired size before loading the image.
Furthermore, you're putting text directly on top of it. Text rendering requires alpha transparency, which requires sampling the underlying image. If you can put the text on an opaque background and put that on top, you'll save some GPU load as well, but I'm actually not sure how much performance that's going to get you. It may not be so big a deal.
You can use Dave Morissey's Subsampling Scale Image View as a drop in replacement of the standard image view.
XML layout:
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:id="#+id/photo"/>
</RelativeLayout>
Set image in code and disable touch:
photo = (SubsamplingScaleImageView) view.findViewById(R.id.photo);
photo.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
photo.setImage(ImageSource.uri(Uri.fromFile(new File("/somepath/file.png"))));
build.gradle:
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
i'm android beginner and trying to program an android app that can dynamic add imageViews to the basic RelativeLayout. It's perform well in my android device but perform poorly in my friend's device which has a big size of screen. I googled for very long time but can't find the solution. Below are part of my code, can anyone help me?
ImageView im = new ImageView(GameActivity.this);
im.setImageBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.image);
RelativeLayout.LayoutParams param =new RelativeLayout.LayoutParams(imageWidth,imageHeight);
wholeView.addView(im, param);
im.setX(x);
im.setY(y);
im.setRotation((float) (-15 + Math.random() * 30 + 90));
dealAnimation = new TranslateAnimation(-x,0,-y,0);
dealAnimation.setDuration(500);
dealAnimation.setRepeatCount(0);
im.startAnimation(dealAnimation);
Where is the size of the bitmaps that you are addding to each ImageView? Which is the total amount of bitmaps that you are adding and in how many time do you performe this operation?
When you say "my device" and "big size of screen", what exactly you mean?
Maybe you're trying to load a very large bitmap? Another point is that you are using the class BitmapFactory which means that you are decoding the bitmap. A large bitmap will use a very large amount of memory when decoded.
Start with appropriately scaled bitmaps, using the various drawable folders to load images (drawable-hdpi, drawable-xhdpi, etc) with a proper initial scale combined with a good distribution of your layouts for each screen size (layout-large, layout normal, etc) to avoid re-scale the bitmaps. And instead use BitmatFactory, try with im.setBackgroundResource(R.drawable.image);
I want to create a bitmap from a view in Android, which basically works fine using the following approach: http://www.aquajava.hu/2011/06/19/converting-view-to-bitmap-without-displaying-it/
However, I want to modify this approach. Basically, my application supports multiple display densities for all kinds of resolution. Instead of creating a bitmap from a view based on the device's display, I want that the bitmap created always relies on the HDPI version. So although the display is maybe smaller I want to create a bitmap with 480 * 800 pixels. If I just increase the size of the bitmap, the font sizes and images still stay small according to the density. I don't want to just scale the image because the resolution would be quite poor then.
So basically, I search for a way to create a bitmap from a view ignoring the density of the view.
Does anybody know how I can solve this?
Have you tried calling setDensity on your Bitmap?
As part of this application I am making, I want to change my wallpaper on my android device based on a bitmap that the user has selected.
I am able to change the background. However, the background is a completely distorted version of the bitmap. Any idea as to why this would happen?Here is my code:
Bitmap bitmap = ((BitmapDrawable)currentDrawable).getBitmap();
this.setWallpaper(bitmap);
My bitmap has a width of 240px and height of 180px. My emulator is of a size 480px by 800px.
I can scale my bitmap to 480px. However, the bitmap still ends up being distorted on the android wallpaper. Any thoughts on how this can be fixed?
Thanks in advance
You should create multiple images, for each potential (and common) resolution. You don't want any scaling, or the image will be distorted.
UPDATE:
Here is a ton of good information on support multiple screen sizes:
http://developer.android.com/guide/practices/screens_support.html
The wallpaper used by the default Launcher is bigger than the actual screen, that's why you can scroll the content and the wallpaper too.
consideration notes: extending SurfaceView, implementing SurfaceHolder.Callback, and loading in bitmap(.png) images to render the canvas (9x9 grid).
I am trying to get the system to resize the images for me so that I don't have to manually create up-to 4 copies of everything (even 3*77 bitmaps is bad overhead [and yes I need all 77 potentially]) I would prefer just having 77 image files in res/drawables(not all of them will be drawn at any given time; at most maybe 38, but needs to be dynamicly capable to change them out).
Q1: how do I get the system to resize the images without doing the white space thing that android.develop talks about for .9.png (considering that all of my grid images have black borders, and need to butt-up together)?
Q2: is there a unifying screen proportionality (4:3, 5:4) that I can fall back on so that diagonal lines don't look really bad?
A1:
Bitmap b= BitmapFactory.decodeResource(context.getResources(), R.drawable.b);
b=Bitmap.createScaledBitmap(b,newWidth, newHeight, true);
A2: i don't think so