4

I a getting an issue due to Aquery library for lazy loading of images on Android 4.4 Kitkat only when scrolling through the GridView/ListView loading images with pagination.

Following are the logs:

12-03 10:39:43.678: W/AQuery(6261): reporting:java.io.IOException: open failed: EMFILE (Too many open files)
12-03 10:39:43.678: W/AQuery(6261): at java.io.File.createNewFile(File.java:946)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.getPreFile(AbstractAjaxCallback.java:1150)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.httpDo(AbstractAjaxCallback.java:1609)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.httpGet(AbstractAjaxCallback.java:1344)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.network(AbstractAjaxCallback.java:1243)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.networkWork(AbstractAjaxCallback.java:1082)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.backgroundWork(AbstractAjaxCallback.java:1014)
12-03 10:39:43.678: W/AQuery(6261): at com.androidquery.callback.AbstractAjaxCallback.run(AbstractAjaxCallback.java:977)
12-03 10:39:43.678: W/AQuery(6261): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
12-03 10:39:43.678: W/AQuery(6261): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
12-03 10:39:43.678: W/AQuery(6261): at java.lang.Thread.run(Thread.java:841)
12-03 10:39:43.678: W/AQuery(6261): Caused by: libcore.io.ErrnoException: open failed: EMFILE (Too many open files)
12-03 10:39:43.678: W/AQuery(6261): at libcore.io.Posix.open(Native Method)
12-03 10:39:43.678: W/AQuery(6261): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
12-03 10:39:43.678: W/AQuery(6261): at java.io.File.createNewFile(File.java:939)
12-03 10:39:43.678: W/AQuery(6261): ... 10 more

It seems I need to Minimize Open Files on External Storage but how to do it? Any idea ???

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
Nitin4Android
  • 864
  • 2
  • 12
  • 25

3 Answers3

6

Android Query release another version (0.26.8) to solve this problem: https://code.google.com/p/android-query/wiki/ReleaseNote#0.26.8

Victor Pinto
  • 447
  • 7
  • 8
2

Edit: I can reproduce it, and it seems to happen on Kitkat only. Previously versions of aquery also have this issue. Checking what's going on now.

Ok I just tested it. The issue is cause my inPurgeable settings:

Why would I ever NOT use BitmapFactory's inPurgeable option?

It will happen when there are too many images displayed. Without the option, app will run out of memory quicker than the file limit (so it's even worse).

What I suggest is limit the number of images in Activity or Fragments that is still in use.

I am checking if there's a better solution, but will likely take some time.

You might also try other image loading library and see if that happens.

Community
  • 1
  • 1
Peter Liu
  • 180
  • 1
  • 5
  • As soon as I press Back button, the App gets crashed with following logs: – Nitin4Android Dec 05 '13 at 10:18
  • 12-05 17:44:19.808: E/InputChannel-JNI(1683): Error 24 dup channel fd 86. 12-05 17:44:19.818: E/InputEventSender(1683): Exception dispatching finished signal. 12-05 17:44:19.818: E/MessageQueue-JNI(1683): Exception in MessageQueue callback: handleReceiveCallback – Nitin4Android Dec 05 '13 at 10:18
  • How can I limit the number of images in Activity or Fragments that is still in use..? – Nitin4Android Dec 05 '13 at 10:20
  • How many images your app is holding? This won't happen until you have 300-500 ImageViews that are not released (hold by an activity or fragments that might or might not be visible). – Peter Liu Dec 06 '13 at 05:43
  • If only a small amount of images are displayed, there's a chance of memory leaking activity or fragments. – Peter Liu Dec 06 '13 at 05:45
  • I tried to keep inPurgeable true and set inInputShareable to false. It seems like it's going well. – nagoya0 Dec 08 '13 at 17:31
  • Thanks Peter for the concern... +1 to U :-) – Nitin4Android Dec 10 '13 at 10:17
1

I met the same problem in KitKat. Fix is following: change options.inInputShareable from 'true' to 'false' in BitmapAjaxCallback.java Every bitmap loaded from any URL is stored to file. And if inInputShareable is true, your process has duplicated file descriptor for sharing. So when >1024 file descriptors are leaked, EMFILE is occured. But actually I can't understand why it worked correctly before KitKat :)

P.S. inInputShareable=false works as inPurgeable=false and leads to rapid OOM :( Correct fix in AQuery is change call of BitmapFactory.decodeFileDescriptor to BitmapFactory.decodeByteArray (Don't use decodeStream!!! It ignores inPurgeable despite its JavaDocs)

And I've found that the issue is related with bug in KitKat: https://code.google.com/p/android/issues/detail?id=65638

Starkom
  • 31
  • 4