android-signaturepad icon indicating copy to clipboard operation
android-signaturepad copied to clipboard

OutOfMemoryException

Open gcmorrison opened this issue 8 years ago • 14 comments

We got a OutOfMemoryException crash report from out production app. First time it's ever happened, but I thought I'd log it anyway in the hopes that you can improve your library :)

Device: Samsung Galaxy Note 10.1 2014 Edition (SM-P605) OS Version: Android 4.4.2

Stack Trace: java.lang.OutOfMemoryError at android.graphics.Bitmap.nativeCreate(Native Method) at android.graphics.Bitmap.createBitmap(Bitmap.java:924) at android.graphics.Bitmap.createBitmap(Bitmap.java:901) at android.graphics.Bitmap.createBitmap(Bitmap.java:868) at com.github.gcacace.signaturepad.views.SignaturePad.ensureSignatureBitmap(SignaturePad.java:471) at com.github.gcacace.signaturepad.views.SignaturePad.addBezier(SignaturePad.java:363) at com.github.gcacace.signaturepad.views.SignaturePad.addPoint(SignaturePad.java:351) at com.github.gcacace.signaturepad.views.SignaturePad.onTouchEvent(SignaturePad.java:159) at android.view.View.dispatchTouchEvent(View.java:8045) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2295) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1622) at android.app.Dialog.dispatchTouchEvent(Dialog.java:761) at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2243) at android.view.View.dispatchPointerEvent(View.java:8240) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4654) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4520) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4078) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4132) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4101) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4212) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4109) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4269) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4078) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4132) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4101) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4109) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4078) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6437) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6354) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6325) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6290) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6517) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method) at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176) at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6490) at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6536) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803) at android.view.Choreographer.doCallbacks(Choreographer.java:603) at android.view.Choreographer.doFrame(Choreographer.java:571) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5476) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) at dalvik.system.NativeStart.main(Native Method)

gcmorrison avatar Mar 18 '16 05:03 gcmorrison

Do you suspect svg to be part of that ?

thomasleveil avatar Mar 25 '16 23:03 thomasleveil

I think the issue is related to the view size: currently the bitmap size depends on view width and height. I need to investigate how to limit that size, based on available heap.

gcacace avatar Mar 26 '16 11:03 gcacace

this might help

thomasleveil avatar Apr 04 '16 12:04 thomasleveil

@gcacace u already begin work in this? If not, i'll. I had a lot of crashes in enterprise software 😟

biliboss avatar Feb 09 '17 18:02 biliboss

It would be great if someone could help looking into that, as unfortunately at the moment I don't have so much time.

gcacace avatar Feb 10 '17 23:02 gcacace

@gcacace can you please look into this issue on priority as I'm also getting a lot of crashes regularly in my application due to this.

harshitjain07 avatar Apr 24 '17 10:04 harshitjain07

  1. You can use thirty party image libs to manager the bitmap, such as fresco. They are optimize the memory, such as use ASM memory.
  2. When you create bitmap, you can set bitmap config to RGB_565 or ARGB_4444. I think it has very small effect, because the signature is black and white.
  3. At last, You make the bitmap small

huanting avatar Jul 31 '17 03:07 huanting

Hi! I also got this bug at production app a week ago.

Lib version: com.github.gcacace:signature-pad:1.2.1

Device:

  • Brand: TCL
  • Model: 5056I
  • Orientation: Portrait
  • RAM free: 245.47 MB
  • Disk free: 7.49 GB

Operating System:

  • Version: 6.0.1
  • Orientation: Portrait
  • Rooted: No

Stack trace: Fatal Exception: java.lang.OutOfMemoryError Failed to allocate a 3548172 byte allocation with 3410256 free bytes and 3MB until OOM dalvik.system.VMRuntime.newNonMovableArray (VMRuntime.java) android.graphics.Bitmap.nativeCreate (Bitmap.java) android.graphics.Bitmap.createBitmap (Bitmap.java:831) android.graphics.Bitmap.createBitmap (Bitmap.java:808) android.graphics.Bitmap.createBitmap (Bitmap.java:775) com.github.gcacace.signaturepad.views.SignaturePad.ensureSignatureBitmap (SignaturePad.java:573) com.github.gcacace.signaturepad.views.SignaturePad.clear (SignaturePad.java:157) com.radaro.mvp.task_completion.view.SignatureFragmentController.lambda$setListeners$0$SignatureFragmentController (SignatureFragmentController.java:78) com.radaro.mvp.task_completion.view.SignatureFragmentController$$Lambda$0.onClick (Unknown Source) android.view.View.performClick (View.java:5205) android.view.View$PerformClick.run (View.java:21164) android.os.Handler.handleCallback (Handler.java:739) android.os.Handler.dispatchMessage (Handler.java:95) android.os.Looper.loop (Looper.java:148) android.app.ActivityThread.main (ActivityThread.java:5417) java.lang.reflect.Method.invoke (Method.java) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:726) com.android.internal.os.ZygoteInit.main (ZygoteInit.java:616)

If someone has a working cure for this bug?

Have a nice day!

Grimald avatar Jul 20 '18 09:07 Grimald

@Grimald take a look into previous comment. I reduced the size of bitmap and it solves the problem.

biliboss avatar Aug 01 '18 18:08 biliboss

is this issue fixed? I am still getting the same error with the latest version.

nishantt12 avatar Mar 02 '20 09:03 nishantt12

Hello there ! I'm getting the following log: E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 3319160) W/ActivityStopInfo: Bundle stats: W/ActivityStopInfo: PersistableBundle stats: [null] D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.fichaatendimento, PID: 27836 java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 3319160 bytes at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161)

I was wondering if I could get some help about this. You think it might be related to the messages wrote above ? Regards.

abraaomelo avatar Mar 25 '21 19:03 abraaomelo

Is there any updates? android:saveEnabled="false" - hotfix for now.

BoykoDmytro avatar Jan 31 '22 14:01 BoykoDmytro

The issue is not fixed in the most "recent" 1.3.1 from 2020. A simple workaround is to create a custom SignaturePad implementation like so an remove the dangling Bundle entry:

import android.content.Context
import android.os.Bundle
import android.os.Parcelable
import android.util.AttributeSet
import com.github.gcacace.signaturepad.views.SignaturePad

class FixedSignaturePad(context: Context, attrs: AttributeSet) : SignaturePad(context, attrs) {
    override fun onSaveInstanceState(): Parcelable {
        val bundle = super.onSaveInstanceState() as Bundle
        bundle.remove("signatureBitmap")
        return bundle
    }
}

A "proper" fix however would be to save the bitmap in the application's cacheDir and just save a pointer to that file in the saved instance state. It's hilarious to think in first place that saving a Bitmap in a save state is a good idea...

realdadfish avatar Jan 26 '24 09:01 realdadfish