I am having lots of images as frames in my resources/drawable folder (let say approx 200). And using this images i want run a animation. The longest animation is of 80Frames. I am successfully able to run the animation on click of the buttons for some, but for some of the animation it is giving me OutOfMemoryError saying that VM can't provide such memory. It is out of VM Budget. I count the size of all of the images its about 10MB. The size of each image is 320x480 in pixels.
I try googling and found that i need to explicitly call the Garbage Collector using System.gc() method. I have done that but still i am getting some time error of memory. Can anyone please kindly help me out in this.
Some Code:-
ImageView img = (ImageView)findViewById(R.id.xxx);
img.setBackgroundResource(R.anim.angry_tail_animation);
AnimationDrawable mailAnimation = (AnimationDrawable) img.getBackground();
MediaPlayer player = MediaPlayer.create(this.getApplicationContext(), R.raw.angry);
if(mailAnimation.isRunning()) {
mailAnimation.stop();
mailAnimation.start();
if (player.isPlaying()) {
player.stop();
player.start();
}
else {
player.start();
}
}
else {
mailAnimation.start();
if (player.isPlaying()) {
player.stop();
player.start();
}
else {
player.start();
}
}
This is the code i have written in on click of a Button.....
Resource file inside res/drawable/anim
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true" >
<item android:drawable="@drawable/cat_angry0000" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0001" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0002" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0003" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0004" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0005" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0006" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0007" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0008" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0009" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0010" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0011" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0012" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0013" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0014" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0015" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0016" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0017" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0018" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0019" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0020" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0021" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0022" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0023" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0024" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0025" android:duration="50"/>
</animation-list>
** The above is the resource file used in setBackgroundResource, same way I am having 10 more file for other different animation. **
Error Log
01-16 22:23:41.594: E/AndroidRuntime(399): FATAL EXCEPTION: main
01-16 22:23:41.594: E/AndroidRuntime(399): java.lang.IllegalStateException: Could not execute method of the activity
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View$1.onClick(View.java:2144)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View.performClick(View.java:2485)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View$PerformClick.run(View.java:9080)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.os.Handler.handleCallback(Handler.java:587)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.os.Handler.dispatchMessage(Handler.java:92)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.os.Looper.loop(Looper.java:123)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.app.ActivityThread.main(ActivityThread.java:3683)
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invokeNative(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invoke(Method.java:507)
01-16 22:23:41.594: E/AndroidRuntime(399): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
01-16 22:23:41.594: E/AndroidRuntime(399): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
01-16 22:23:41.594: E/AndroidRuntime(399): at dalvik.system.NativeStart.main(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): Caused by: java.lang.reflect.InvocationTargetException
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invokeNative(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invoke(Method.java:507)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View$1.onClick(View.java:2139)
01-16 22:23:41.594: E/AndroidRuntime(399): ... 11 more
01-16 22:23:41.594: E/AndroidRuntime(399): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.loadDrawable(Resources.java:1709)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.getDrawable(Resources.java:581)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.AnimationDrawable.inflate(AnimationDrawable.java:267)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:787)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.Drawable.createFromXml(Drawable.java:728)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.loadDrawable(Resources.java:1694)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.getDrawable(Resources.java:581)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View.setBackgroundResource(View.java:7533)
01-16 22:23:41.594: E/AndroidRuntime(399): at talking.cat.CatActivity.middleButtonClicked(CatActivity.java:83)
Same way i have different buttons for different animation... Thanks
I had this problem and solved it by doing the two following things:
My animation was still failing to load on some phones after doing step 1. Step 2 got it working on those phones.
Hope this saves somebody else some time.
EDIT: I was still experiencing crashes after going to the Activity that plays the AnimationDrawable but I have it working now. Here are the additional things I did:
Here is code I am using for creating the AnimationDrawable:
And code for freeing up the bitmaps when you are done using them. You could do this in OnPause or OnDestroy. _loadingAnimation is my AnimationDrawable created above. I would love to know what SetCallback() does for you in this case. I just copied that from somewhere else on SO.
Ted
I spent a lot of time on this and have two different solutions, both good..
First, the problem: 1) Android loads all of the images into RAM, in uncompressed Bitmap format. 2) Android uses resource scaling, so on a phone with an xxxhdpi display (such as LG G3), each frame takes up a TON of space, so you quickly run out of RAM.
Solution #1
1) Bypasses Android's resource scaling. 2) Stores the bytearrays of all files in memory (these are small, especially for JPEGs). 3) Generates Bitmaps frame-by-frame, so it is almost impossible to run out of RAM.
Disadvantages: It spams your logs as Android is allocating memory for new Bitmaps and recycling old ones. It also performs lousy on older devices (Galaxy S1), but performs nicely on current budget phones (read: $10 Alcatel C1 I picked up at BestBuy). Second solution below performs better on older devices, but could still run out of RAM in some circumstances.
** Solution #2 **
It loads the XML resource, parses it and loads the raw resources - thereby bypassing Android's resource scaling (which is responsible for most OutOfMemoryExceptions), and creates an AnimationDrawable.
Advantages: Performs better on older devices (eg. Galaxy S1)
Disadvantages: Can still run out of RAM as it's holding all of the uncompressed Bitmaps in memory (but they are smaller because they are not scaled the way Android normally scales images)
If you are still having memory issues, use smaller images... or store the resource name + duration, and generate the byte-array + Drawable on each frame. That would almost certainly cause too much chopping between frames, but uses almost zero RAM.
I had the same problem. Android loads all the drawables at once, so animation with many frames causes this error.
I ended up creating my own simple sequence animation:
Usage:
I have solve this problem by put all the images in array and use delay after show each of them. The array of images source in res/string
<!-- Array table for the pictures to show on the spinner--> <array name="spinner_list"> <item>@drawable/arrows_loop__00000_org</item> <item>@drawable/arrows_loop__00005_org</item> <item >@drawable/arrows_loop__00010_org</item> <item>@drawable/arrows_loop__00015_org</item> <item >@drawable/arrows_loop__00020_org</item> <item >@drawable/arrows_loop__00025_org</item> . . . </array>
I declare about the spinner imageView private static ImageView imagespinner;Then in my class I call it here:
and then on runimage I do the loop with delay like this:
public void runimage(final TypedArray array, int index) {
so I run all the images with 55milsec delay on the imagespinner. After finish do the nex job.