Search code examples
javaandroidimagebitmaptrace

How do i trace which image is the killer of my app?


I am having trouble with an image that is being drawn that is too big and its killing my app.

The following error occurs:

java.lang.RuntimeException: Canvas: trying to draw too large (numbernumbernumberbytes) bitmap.

I have went through my app and I have disabled all large images that were loaded directly. Images that are loaded with Glide (Image loading library, https://github.com/bumptech/glide) should not be a problem.

The error still occurs and I was wondering if there was a way to trace the error. To see exactly which image is causing the problem.

Is there a way to trace this?

EDIT1:

The complete stacktrace of the error:

07-07 19:22:21.468 D/AndroidRuntime: Shutting down VM


                                     --------- beginning of crash
07-07 19:22:21.469 E/AndroidRuntime: FATAL EXCEPTION: main
                                     Process: com.linkhubapp, PID: 20097
                                     java.lang.RuntimeException: Canvas: trying to draw too large(132710400bytes) bitmap.
                                         at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:260)
                                         at android.graphics.Canvas.drawBitmap(Canvas.java:1420)
                                         at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:545)
                                         at android.widget.ImageView.onDraw(ImageView.java:1286)
                                         at android.view.View.draw(View.java:18318)
                                         at android.view.View.updateDisplayListIfDirty(View.java:17296)
                                         at android.view.View.draw(View.java:18080)
                                         at android.view.ViewGroup.drawChild(ViewGroup.java:3966)
                                         at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3752)
                                         at android.view.View.updateDisplayListIfDirty(View.java:17291)
                                         at android.view.View.draw(View.java:18080)
                                         at android.view.ViewGroup.drawChild(ViewGroup.java:3966)
                                         at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3752)
                                         at android.view.View.updateDisplayListIfDirty(View.java:17291)
                                         at android.view.View.draw(View.java:18080)
                                         at android.view.ViewGroup.drawChild(ViewGroup.java:3966)
                                         at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3752)
                                         at android.view.View.updateDisplayListIfDirty(View.java:17291)
                                         at android.view.View.draw(View.java:18080)
                                         at android.view.ViewGroup.drawChild(ViewGroup.java:3966)
                                         at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3752)
                                         at android.view.View.updateDisplayListIfDirty(View.java:17291)
                                         at android.view.View.draw(View.java:18080)
                                         at android.view.ViewGroup.drawChild(ViewGroup.java:3966)
                                         at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3752)
                                         at android.view.View.draw(View.java:18321)
                                         at com.android.internal.policy.DecorView.draw(DecorView.java:919)
                                         at android.view.View.updateDisplayListIfDirty(View.java:17296)
                                         at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:692)
                                         at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:698)
                                         at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:806)
                                         at android.view.ViewRootImpl.draw(ViewRootImpl.java:3121)
                                         at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2917)
                                         at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2509)
                                         at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1508)
                                         at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7084)
                                         at android.view.Choreographer$CallbackRecord.run(Choreographer.java:927)
                                         at android.view.Choreographer.doCallbacks(Choreographer.java:702)
                                         at android.view.Choreographer.doFrame(Choreographer.java:638)
                                         at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:913)
                                         at android.os.Handler.handleCallback(Handler.java:751)
                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                         at android.os.Looper.loop(Looper.java:154)
                                         at android.app.ActivityThread.main(ActivityThread.java:6682)
                                         at java.lang.reflect.Method.invoke(Native Method)
                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

Solution

  • (I'm using Android Studio) ... To know which image it is, it takes a small bit of debugging. Do the following:

    1. First, run the app and allow it to crash.
    2. Look to the LOGCAT window. There you will find the crash: "java.lang.RuntimeException: Canvas: trying to draw too large(137080832bytes) bitmap." - Below that, look for "at android.graphics.drawable.BitmapDrawable.draw" and it will have a clickable link to the right. It should be the first clickable link displayed under the exception text above. Click the link.
    3. Clicking the link should highlight a line of code, likely the following:

      canvas.drawBitmap(bitmap, null, mDstRect, paint);

    Set a breakpoint on that line of code. Then run the app again using the 'Debug app' button. The program will stop at the above line of code. You will need to click the 'Resume Program' button and keep track of how many times you click that button before the program crashes. Then run the app again in debug mode again, allow it to break on that line of code, then click the 'Resume Program' button the number of times you clicked the button previously, minus one time. So if I clicked the Resume Program button 4 times to get to the crash, you will want to click it 3 times and stop there. This will be the execution time of the code that causes the app to crash.

    1. The breakpoint for that line of code should be hit and the program halted, ready for you to do something. Hover the mouse over the word 'bitmap' in the line of code:

      canvas.drawBitmap(bitmap, null, mDstRect, paint);

    Don't hover the mouse over the word 'drawBitmap' - just the word 'bitmap'. A small yellow window should appear below the line of code that contains a plus sign (+) and '{Bitmap@####}'. Click the plus sign. Notice that to the far right of the first line of text shown is a clickable link that reads 'View Bitmap'. Click on that link and you should be shown the picture that the app is trying and failing to load.

    And that's it!