Possible memory leak in Square/Picasso for Android - android

I am part of a team developing a commercial media app. Part of the functionality is to allow the user to customise a ViewGroup montage of ImageViews with their own images retrieved either from Gallery or direct from Camera. I am using the following Picasso call to do this:
mPicasso.load(uri)
.resize(newWidth, newHeight)
.into(container);
where mPicasso is Picasso.with(appContext()) and newWidth and newHeight are dimensions calculated from the source height and width such that aspect ratio is maintained and the resulting image is 1MP. Typically, the sources are between 8 and 16MP.
If I have a montage of say, eight ImageViews, and I keep adding images to each one in turn, the app eventually crashes. Device only has so much memory, right? Eventually if you keep adding infinite images you're going to run out. What really concerns me, however, is that the app will crash half-way through replacing the eight images. To be clear, you've added your eight images and you've gone back to the top and started replacing those images with different ones and you get to roughly the fourth before the crash.
I would have expected that once an image has been replaced, the old one would be cleaned up. I can fix this by reducing the max size down to 100KP but the problem with that is I imagine I am just delaying the crash. Furthermore, the user has the ability to zoom the image and with such a low resolution, it starts to look knarly quite quickly.
I have posted the crash log here:-
https://gist.github.com/mylesbennett/452c992f6912039ea62d
because it's too long to paste direcly in stackoverflow.
Any suggestions of workarounds/ fixes etc. would be greatly appreciated.
(the crash point in TemplateImageView.isScaleInitialised is where the app is attempting to allocate memory to a nine-value float array:
float[] values = new float[9];
so I am guessing that this is just the straw that broke the camel's back)

Related

Out of memory exception on inflating layouts

I am getting random out of memory exceptions in my app caused by inflate exceptions.
I have 7 fragment (difficulty) activities which launch their own activities via buttons. Each fragment has a scroll view with 30 buttons (levels).
I have set it up so that i can swipe across to each fragment and the fragment takes up the entire screen.
Occasionally when i swipe a few times and then select a random button from a group of 30 it will crash. It tries to load the activity and gives an out of memory exception with an inflate exception on a random line. The line always falls on an imageView or imageButton in the xml file. The activities that load are a grid of imageViews and imageButtons.
I do not get the exception much but it is something i want to fix. I have looked at many other out of memory exception questions although none have helped me. I have done a Memory analyser test and it shows nothing out of the ordinary.
I believe that the imageViews and imageButtons are using too much memory, although i only ever have one activity open at once.
It IS because of your images that are loading. When you load an image and you move around the page and view another image the heap increases. As you continue the process of viewing random images the heap grows even more until your app crashes. It's like stacking books on a glass table. You either move(cache) a book(image) or the glass(app) breaks. You should use an imageloader to load your images.
https://github.com/nostra13/Android-Universal-Image-Loader
You've mentioned that it always falls on an ImageView and ImageButton - and this is the clue to solve this problem. You get OOM 'cause background resource of this view has high resolution and takes a lot of memory. Try to lower resolution of this image.
Also you've mentioned that you have a ScrollView and this means that you keep in memory every 30 items. Probably you'd better change it to RecyclerView backed by adapter.
Just had the same problem and I'd like to simplify all the things said here:
Simply: reduce your images sizes.
Don't use 1080X1920 images... It's too high res.
Such image, even if compressed, when deployed will catch about 1080X1920X4B = 8.2MB (The GPU has to deploy it to it's full original resolution... That's why compression won't help but reducing the needed memory size...) and this i RAM that we're talking about..
Take Gimp or Photoshop and down scale the image to, say, 1/4: 540X960, and you won't feel the difference.. Belive me, been there already.
Beware of the memory consumption of images and videos.
Hope this helps,
James

Frame animation problems android

I am stuck showing frame animation in android. My problem is that I have to animate 36 images. The smallest image is 69 kb in size and the biggest(last frame) is 526kb. A total of 11mb. I know its insane but I need to do it. See images below. The app is already made for iphone and I have to port it to android.
Requirements:
smooth animation
no frame loss
consistent with iphone
The solutions I tried are:
AnimationDrawable by providing in xml files. Problems: the start time is almost 6 -12 seconds. Images lose frames so jaggy experience.
Change imageview bitmap inside a handler. Problems: Frame loss and Out of memory
Create a custom imageview class. Define a method showAnimation() and inside it update bitmap and invalidate() the view unitl the last frame. Problems: Not fitting my requirement. This by far gave the best result but not half as required.
I am a noob in opengl and gamedevelopment. I am unable to find any alternative to my problem. Please help.
Smallest image:
Last image:
I can visualize the effect you are aiming at.I guess doing this will require pushing in different images onto the same imageView, with incremental frame rate.|
The accuracy will depend on the number of images you have. Greater the number of images finer will be the precision.
Also you need to implement incremental frame rate. So that it gives a smoother feel.
Doing this should be possible using a simple loop to change the image resource of the imageView Controller. There must be lag between two iterations, this lag will actually be the frame rate.
I think this can give satisfactory results.
Going for openGL, however, you will not need all these images. It will just require one image of the card that will be animated and duplicated to create the final image. This however is a complex piece of task(I think) so if you are catching some dead lines, you must go for a non-openGL solution like the 1st one, I have suggested.

android out of memory for including some image buttons

Actually I have for so long wish to know how to present graphics in a proper way.
In an activity, I have the following:
a background (png, full screen, 768*1280, 1.36MB)
3 icons (each icon has pressed and not pressed: 2 states, using 1 png 400 * 400, 300KB each), i.e. 3 icon * 2 pic * 300KB = 1.8MB
some more textviews
When the app starts off and directly goes to this activity, everything is ok, the activity can be presented properly.
Yet somehow when the app has run for some other activities, and then goes to this activity through a dialog box, then most of the time errors will occur, as follows:
Out of memory on a 15728656-byte allocation.
Question:
I have researched for sometime and some say to bitmap.recycle(), yet how to implement? through the onCreate? or actually 400*400 is too big?
If I want to change the background of an activity upon users' choice, i.e. when he presses button A, the background changes to bgdA, presses button B will change background to bgdB... in that way how that can be achieved?
Many thanks!
Depending on where your asset is stored is the amount of memory it might take, since scaling factor is calculated between the difference of densities, this is a little gray area because I haven't found any official android documentation that backs this info up, however I've seen that error so many times and this is the way I handle it.
1.- If you don't have the asset in the proper drawable-(density), this will cause problems because depending on the devices you are actually supporting, you should put the asset in drawable-xxhdpi or drawable-xhdpi, you will notice how the memory will decrease considerably
2.- If you don't want to mess with densities because it's a generic image which don't have much details(like a simple background), then add the asset in the drawable-nodpi folder, it will prevent android from trying to scale the asset it self..
3.- As good practice, try to create the asset with the proper size for the proper densities, 400 x 400 seems like too much for an icon, this will also prevent you from OOM, not only in this activity, but for other activities that might also need to load a good amount of assets, giving scalability to your app..
Always take on count that leaving the "resize" of an Image to the OS might cause huge amounts of memory allocated because the OS will try to resize it based on the formula width * height * 4bytes, the 4 byes are for ARGB of each pixel, 1 byte per color or alpha, so if your image is for example 1090 * 1920, it could easily become internally 8.3MBs even tho the actual image size is only a few KBs, and if it tries to scale it, it might double it's size too.
Hope this Helps
Regards!
Make sure you have a copy of your image for every drawable folder in you res, for example if you runnig your app on the S4 phone and you don't have all the images in the drawable-xxhdpi folder you will run out of memory even with reasonably small images.
Also if you need to change background at run time use setBackgroundResource.
Hope it helps
This is the common problem in android here is the proper solution
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
In easy words you have to scale the image down according to your requirement

Android OutOfMemory exception - Is there another approach for my needs?

My app is loading a large image (a house floorplan), then drawing touch-reactive objects (furniture, lamps etc.) on the image. I have a base image file included with my app but the objects come from coords in my database.
I've successfully deployed the app in multiple iterations, but now I need to use larger base images and BitmapFactory is causing an OutOfMemory exception on many devices (both old and new devices; anything with < 32MB heap seems to crash). I've read the 157 OOM questions on SO, but I'm afraid the link they all seem to point to won't help me since resolution / zooming is critical to the app's function.
I've tried to test the device's available memory before loading, but the results are spotty at best (some devices like the galaxy S3 report plenty of heap but still crash). I've also tried decreasing resolution but the image became unusable when reduced to a safe size based on the above test.
Is there another way to implement this design without ever using bitmaps?
I need to:
Load large base image
Create clickable shapes on top of the base image, maintaining their position / scale relative to the base image
BONUS: in the iOS version of my app, I can do SVG-style text scaling so a long label on a small object will stay inside the object
instead of running across the map(and will be invisible until the
image is zoomed). Replicating this in android would make me a happy
code monkey.
I can post code if needed, but you've all seen it before (almost all of it came from SO).
Thanks in advance for reading, and for any help you can give.
you have a few options:
break your large image into tiles, load these tiles into an array, and move a camera object around and only load tiles that need to be drawn, as the comments suggest.
make your image small and scale it up using 'android:scaletype`
Draw lines and curves on a Canvas object at runtime.
Use OpenGL
The appropriate solution really depends on how you want it to look. Tiling will take more dev effort but will look better, just be careful that you are properly cleaning up any tiles that aren't being drawn...
dynamically scaling will be easier, but you cannot guarantee the image won't be blurry.
Drawing on a Canvas object at runtime could work well-- just use Lines of different width and circles and Rects etc.
Using OpenGL will have the steepest learning curve, and might be overkill. This depends on your purpose.
You might like to look into using a "largeHeap"
http://developer.android.com/reference/android/R.styleable.html#AndroidManifestApplication_largeHeap
Here are some options:
1) Use tiles. Use tiles and dynamically load your data. Honestly, this is the best solution. With this solution you can load arbitrarily large images.
I've successfully used this approach for an endless paint canvas and it works quite well. You really only need to draw what is directly visible to the user. Tiles is a way to cast away pieces you don't need. A pyramid of tiles (where you pre-downsample your images and create more tiles), allows you to do this in a clean and fast way.
2) Use native code. The memory restrictions on native code are not the same as Java code. You can get away with allocating more memory.
3) Use OpenGL. Once again, the memory restriction for OpenGL are not the same as Java code.
4) Convert your original plan to an SVG and use an SVG library like this one.
5) Use "largeHeap". I strongly discourage this, as I think a largeHeap is rarely the solution, there are generally cleaner ways to approach the problem.
if the image is static , you might wish to use this nice library:
https://github.com/ManuelPeinado/ImageLayout
if the library doesn't support auto-downsampling of the image, you should do it by yourself, in order to use the best image for the current device (so that you won't get OOM).
for auto-sizing text , you might have some luch with the next post:
Auto-fit TextView for Android

How to clean up bitmap resources

I wanted to ask this question that was asked a few times before. Sorry if I am re-itterating but it is not clear to me as to what is the best solution here.
The question is "how to clean ImageView bitmap resource after its been used so we don't have references to it in memory?".
Here is an example:
Screen 1 redirects to Screen 2
Screen 2 contains control A (preview of large photo)
Control A contains ImageView B
ImageView B is set when control A is initiated
Everything works fine the first time around. Once control A is done I redirect from Screen 2 to Screen 1. At this point all references of control A or ImageView B or Bitmap that its using should be dead. THEY ARE NOT!!!
I've tried all kinds of solutions including bitmap.recycle(), adding finalize() into Control A, System.gs() and nulling control in variouse places such as onStop() and onDestroy(), and everything else that's on screen 2, nothing works!
The problem is when I revisit the screen second time around so going from screen 1 to screen 2 (i.e. creating preview of photo again) I get out of memory exception. It is my understanding that the reference of the previous bitmap is not cleaned up.
How do I KILL it just before I redirect back to Screen 1?
One thing I noticed. If I reduce the size of the photo by, say cropping or making a smaller size of the image everything goes smooth, few times... before I get same issue. So basically it just takes a bit longer to fill up.
I would really appreciate some solution here as this is critical.
You probably have a memory leak , this video might help you in finding the problem Google I/O 2011: Memory management for Android Apps.
Note : pre 3.1 bitmaps are store in VM heap memory but in native memory , which causes lot of problems in noticing leaks,for further info refer the video
Have a look at how WeakReference is used.

Categories

Resources