This question already has answers here:
Android:java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM
(31 answers)
Closed 3 years ago.
I have a RecyclerView in an android app. I am doing some kind of file explorer.
When I plug my own device on the computer, it runs out of memory when I reach the Camera folder in DCIM folder.
This is because there are a lot of pictures in there and I am trying to show them as the ImageView instead of the usual file icon drawable.
When the images are loaded the app runs out of space so it crashes
I implemented the app using a RecyclerView thinking it is going to recycle the views and not run out of memory or lag. But it doesn't seem to work.
I tried doing some kind of workaround by loading images only for the visible portion of the RecyclerView but it requires a lot of twists and it didn't work in the end.
Is there a way to load lot of images and make sure they don't take too much space in RAM. I'm using an old phone and I'd like my app to work on it. It is a Galaxy Ace II.
use glide
add com.github.bumptech.glide:glide:4.10.0 in your dependencies
Why handling images in the app, using Glide or Picasso is stronly recommended.
1- To implement Glide https://github.com/bumptech/glide (that I prefer)
2- To implement Picasso https://square.github.io/picasso/#download (also a strong library)
They handle images professionally. They have tools to avoid OOM caused by images. you should follow tutorials to implement and use them.
But OOM is not only because of the images. Whole application must be observed.
https://stackoverflow.com/a/58358334/11982611 this post can help for this.
After implmenting, To make resizing with Glide
Glide.with(mCtxt).load( image uri or url or drawable )
.error( image when error occurs )
.override(320,180) // overrided width and height
.centerCrop()
.into( imageview );
Whatever you are using, you should adjust your images according to mobile device
Thank you for your answers.
I ended up doing the following:
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
bitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, false);
imageView.setImageBitmap(bitmap);
It is still very laggy even at 50x50 pixels. I may try GLIDE library.
Related
I have three general questions regarding android's drawable folders.
Do i put different sized images in each of these folders, or will the images automatically scale themselves? As in, does android decrease the quality of the .bmp files automatically if placed in these folders?
When using the android design preview screen, will the appropriate image from the appropriate drawable folder be shown? If I have to make different sized images for each folder, I want to ensure that what i'm seeing in the design preview matches what is shown on other devices.
Lastly, do the drawable folders, if used, help to avoid the issue with failing to allocate memory for drawables on devices? I have had to scale my images down, and yet my college's phone still cannot allocate enough resources.
I couldn't find answers to these specific questions anywhere, so i'd really appreciate the help with these!
1) You don't need the different folders if you will put the same things in those folders. The designer/developer puts the resources that most adapt to that configuration.
2) You can select what kind of device you're previewing the design with (resolution and dpi), on the design tools. It will attempt to load the appropriate resource for that configuration.
3) Loading smaller images into memory may be helpful, as well as resizing them before displaying them (libraries like Picasso can do this out of the box), or you could be looking at a leak of some sort.
About your first question, you should create four different drawable folders in app>res in order to provide different devices (with different screen sizes and densities) more convenient images.
/drawable-ldpi For low density screens.
/drawable-mdpi For medium density screens.
/drawable-hdpi For high resolution screens.
/drawable-xhdpi For extra high resolution screens.
Android does not decrease the quality of .bmp files when they are allocated in those folders. You have to fill each folder with the correct sized images.
About second question, I am not sure whether the android design preview screen uses the correct images or not, but in a real app running on a phone, it will.
And third question: sorry, but not.
Good luck!
Ad 1 I always find it really helpful to load drawables to my project using Android Drawable Importer plugin. It will take care of loading appropriately-sized image into appropriate drawables folder.
Ad 3 If that works for you, maybe try loading images from server using tools like Glade or Picasso? That way you don't clutter your app with unnecessary resources, making it too heavy data-wise. Use a local drawable as placeholder only, in case there's no internet connection.
I'd also recommend using .png over .bmp format, .png are lossless and compressed, meaning your images can get significantly smaller while not losing quality.
You have to put images in different folders as per the image size. it will not generate automatically.
You can not select image for that screen. you can just select different screen sizes android studio will automatically use proper images for that.
For memory issue you can add this line in manifest :
android:hardwareAccelerated="true"
I have an app where I have to play png animations when a user answers a question.
All png images are 320 x 569. My current implementation is done using animation-list using the technique mentioned here:
https://www.bignerdranch.com/blog/frame-animations-in-android/
and inside the Java class I used the code mentioned here:
Android AnimationDrawable and knowing when animation ends.
The animations were working fine but I was facing OutOfMemory Exception very frequently. So I added the following lines to the code from this post:
Animation Drawable causing OutOfMemoryError on second run in Android
and this solved my OOM problem. However, I am still facing the problem of recycled bitmaps when I run it for the 3rd or 4th time.
Is there any other way that we can implement png animations without the bitmap recycle issue?
Working in android studio. I'm importing an image into an imageview but as I test my app across different devices the images becomes a bit distored. I'm assuming this is because of different resolution/size of the devices. Is there anyway to maintain the same image size across all of the different android devices? Thank you.
First of all your image size must be larger than you're trying to support device(s). If your image is in app resources, you can resize it for hdpi, mdpi, xhdpi, xxhdpi, etc. and if the range is not suitable for the screen(s), you can crop in center or something like that. But if you get this image from a URL, you had better do this with Retrofit that does caching and background task.
Set to your ImageView android:scaleType="centerCrop". That should solve your problem.
I have an ImageView in a RelativeLayout:
<ImageView
android:id="#+id/image"
android:src="#drawable/image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
It works on many devices (phones and tablets) and emulators, but does not work on Google Nexus 5 with Android 6. The application works perfectly but the ImageView background is not displayed.
(Image is in drawable folder and I change the image with setImageResource)
I also got the same problem, in which my image show in all android version rest of Android 6.0.
I was testing my application in android 5.0 and android 6.0, that time image shown properly in android 5.0 but in android 6.0 image does not load in Imageview.
I have used src and background both property but did not get the image in Imageview in android 6.0.
Then, To solve this problem I checked my logcat and I got below string in logcat.
W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (3240x5760, max=4096x4096)
I searched related this string and got the solution for this, it is Android 6.0 does not give permission to do the heavy process in UI Thread. If your image is small in size and resolution, then you can use src or background for the load it. but your image is too heavy then Android 6.0 skip this process in UI Thread.
But, You can solve this by use of below solutions.
Solution 1:
Resolve it by use of third party library like Glide for load heavy images.
I have solved it with the use of this.
Solution 2:
Add a drawable-nodpi folder in res, put the image in it and simply use it with src in Imageview tag.
Images come in all shapes and sizes. In many cases they are larger
than required for a typical application user interface (UI). For
example, the system Gallery application displays photos taken using
your Android devices's camera which are typically much higher
resolution than the screen density of your device.
Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. The lower resolution version should match the size of the UI component that displays it. An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.
Displays an arbitrary image, such as an icon. The ImageView class can
load images from various sources (such as resources or content
providers), takes care of computing its measurement from the image so
that it can be used in any layout manager, and provides various
display options such as scaling and tinting.
Remove android:adjustViewBounds="true"
Use Small Size (Resolution) oriented image .
Advice
You can use public void setImageResource (int resId)
Sets a drawable as the content of this ImageView.
This does Bitmap reading and decoding on the UI thread, which can
cause a latency hiccup. If that's a concern, consider using
setImageDrawable(android.graphics.drawable.Drawable) or
setImageBitmap(android.graphics.Bitmap) and BitmapFactory instead.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageResource(R.drawable.image1);
Read Drawable-hdpi, Drawable-mdpi, Drawable-ldpi Android
To declare different layouts and bitmaps you'd like to use for the
different screens, you must place these alternative resources in
separate directories/folders.
This means that if you generate a 200x200 image for xhdpi devices, you
should generate the same resource in 150x150 for hdpi, 100x100 for
mdpi, and 75x75 for ldpi devices.
I was also facing slightly different image view issue on Nexus 5 with 6.0. It was like, image was coming when I reached to the page (having custom keyboard) but if I tap on device back button, image view was hiding (Hiding Custom keyboard).
So what I did, I removed the android:adjustViewBounds="true from the layout, for me its working fine. If you want, you can remove scaletype also.
Still don't know why its happening. I am waiting for proper solution.
move your image to drawable-nodpi instead of drawable.
Basically if u put a image in drawable folder it will be treated as drawable-mdpi so android will resize to fit xxhdpi that is nexus 5 ,
and since the bitmap becomes large it wont display
I was able to load an imageView on API23.
I had faced similar issue when the image was not getting displayed on certain Mi, Vaio devices. I narrowed it down to be the problem of image resolution being too high for those specific devices. So I used Glide image loader library to lower the resolution of an image only while opening it on image view(else the orignal size was saved in SD card) using the following code.
Glide.with(context).load(imagePath).override(1280,720).fitCenter().into(imageView);
I am currently working on a wallpaper application. Is there a way to make a bitmap look less blurry and more crisp once it is set as a wallpaper?
Does it just require cropping the picture and resizing it to fit the size of the screen perfectly, or there is some other way?
P.S. I read that the application wallpaper set and save is able to deliver very good quality wallpapers once launched!
Where are you saving the bitmap? Try placing it in /res/raw as opposed to /res/drawable This prevents android from optimizing the image file, and should make it crisper.