[Bug]: App should be reliably usable on low memory devices
Opened this issue · 2 comments
Summary
Our app used to function decently well on low memory devices. Over time, it has become severely unreliable on such devices. I have a low memory device (1GB RAM) and test the app in it from time to time. I was testing the v5.1.0 release candidate on the device. The app crashed very often with a OOM exception. It crashed when trying to view an image, when trying to initiate an upload (specifically after picking the image) etc. The images weren;t that huge. The app crashes even for images of size around 2.5MB.
We need to work on identifying the root cause and figure out how to handle this gracefully rather than ending up with OOMs.
Steps to reproduce
- Install app on a low-memory device.
- Try to use standard functionalities of the app like upload, viewing contributions
- Observe if the app functions smoothly.
Expected behaviour
App works fine without issues on low memory devices.
Actual behaviour
App crashes often on low memory devices.
Device name
Samsung J1 Ace (J111F; 1GB RAM)
Android version
Android 5.1
Commons app version
main
Device logs
One such OOM exception when trying to initiate an upload. Specifically after selecting the image.
java.lang.OutOfMemoryError: Failed to allocate a 48000012 byte allocation with 4194304 free bytes and 33MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:863)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:839)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:488)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:526)
at android.graphics.drawable.Drawable.createFromPath(Drawable.java:1207)
at android.widget.ImageView.resolveUri(ImageView.java:798)
at android.widget.ImageView.onMeasure(ImageView.java:895)
at android.view.View.measure(View.java:18926)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:728)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:464)
at android.view.View.measure(View.java:18926)
at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1638)
at android.view.View.measure(View.java:18926)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:728)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:464)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1435)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:721)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:612)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1435)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:721)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:612)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:3076)
at android.view.View.measure(View.java:18926)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2411)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1429)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1677)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1314)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7057)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:829)
at android.view.Choreographer.doCallbacks(Choreographer.java:606)
at android.view.Choreographer.doFrame(Choreographer.java:576)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:815)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6934)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Another such OOM exception when trying to upload
java.lang.OutOfMemoryError: Failed to allocate a 192000012 byte allocation with 4193584 free bytes and 114MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:863)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:839)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:488)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:526)
at android.graphics.drawable.Drawable.createFromPath(Drawable.java:1207)
at android.widget.ImageView.resolveUri(ImageView.java:798)
at android.widget.ImageView.onMeasure(ImageView.java:895)
at android.view.View.measure(View.java:18926)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:728)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:464)
at android.view.View.measure(View.java:18926)
at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1638)
at android.view.View.measure(View.java:18926)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:728)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:464)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1435)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:721)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:612)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1435)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:721)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:612)
at android.view.View.measure(View.java:18926)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5908)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:3076)
at android.view.View.measure(View.java:18926)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2411)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1429)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1677)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1314)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7057)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:829)
at android.view.Choreographer.doCallbacks(Choreographer.java:606)
at android.view.Choreographer.doFrame(Choreographer.java:576)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:815)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6934)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199
Screen-shots
No response
Would you like to work on the issue?
None
Leak Canary was reporting many Memory Leaks
. Fixing memory leaks might reduce memory usage overall and improve performance on low-RAM devices.
Even on a Pixel 9 Pro the app quickly becomes unusable and ends up being kicked out of memory when I switch to another map to double-check something. This started happening recently.