9

I'm getting a IllegalStateException: underflow in restore exception, which is causing my application to crash. This started happening after android 4.3 update. On android 3.0 - 4.2.x it works fine.

The exception happens on the second

canvas.restore();

Given below is my drawing code

private void doDraw(Canvas canvas) {
        if(mTickerBackGround!=null && (!mTickerBackGround.isRecycled())){
            canvas.drawBitmap(mTickerBackGround, 0, 0, null);
        }
        if((mBitMapBuffer!=null)){
            canvas.save();
            canvas.translate(mX, 0);
            if(!mBitMapBuffer.isRecycled()){
                canvas.drawBitmap(mBitMapBuffer, 0, 0, null);
            }
            canvas.restore();

            if(bitMapWidth+mX<mCanvasWidth){
                canvas.translate(bitMapWidth+mX, 0);    
                if(!mBitMapBuffer.isRecycled()){
                    canvas.drawBitmap(mBitMapBuffer, 0, 0, null);
                }
                canvas.restore();                   
            }

            if(bitMapWidth+mX<=0){
                mX = 0;
            }else if(Math.abs(mX)>(bitMapWidth)){                   
                mX= mCanvasWidth; 
            }

            mX-=TickerConstants.SCROLLING_SMOOTHNESS*density;;
        }
        if(mLogo!=null && (!mLogo.isRecycled())){
            canvas.drawBitmap(mLogo, mCanvasWidth-(60*density), mLogo.getHeight()/6, null);
        }
    }

My question is

  1. What is the meaning of this error?
  2. How do i fix this error?

Stack trace message generated is . Line 165 corresponds to second canvas.restore()

08-13 18:13:09.083: E/AndroidRuntime(14139): FATAL EXCEPTION: Thread-506 08-13 18:13:09.083: E/AndroidRuntime(14139): java.lang.IllegalStateException: Underflow in restore 08-13 18:13:09.083: E/AndroidRuntime(14139): at android.graphics.Canvas.restore(Native Method) 08-13 18:13:09.083: E/AndroidRuntime(14139): at com.my.package.name.ticker.TickerSurfaceView$TickerThread.doDraw(TickerSurfaceView.java:165) 08-13 18:13:09.083: E/AndroidRuntime(14139): at com.my.package.name.ticker.TickerSurfaceView$TickerThread.run(TickerSurfaceView.java:128)

prashant
  • 3,570
  • 7
  • 40
  • 50

2 Answers2

14

The bug is in this section of your code:

    if(bitMapWidth+mX<mCanvasWidth){
        canvas.translate(bitMapWidth+mX, 0);    
        if(!mBitMapBuffer.isRecycled()){
            canvas.drawBitmap(mBitMapBuffer, 0, 0, null);
        }
        canvas.restore();                   
    }

You are calling restore() without calling save() first. You don't even need that call to translate() either, you could just pass the x and y coordinates to the drawBitmap() call.

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • Thanks. I'm gonna try that. Could you please also explain, what the exception message mean ? – prashant Aug 14 '13 at 13:19
  • So i tried your suggestion and it is not crashing now. I've also incorporated your suggestion regarding the translate call. I'll continue testing on some OS variations. Thanks for your response. – prashant Aug 14 '13 at 14:08
  • I encountered very similar issue except in my case the offending code is closed-source from a 3rd party vendor. We're currently chasing the vendor to fix, but in the meantime is there any other alternative -- eg: restoring behavior of sdk 4.2.2 < ? – gerrytan Oct 31 '13 at 05:53
  • 3
    It also worked for me, i just put a canvas.save() before and it worked – Rako Apr 29 '14 at 12:09
3

public void restore ()

Added in API level 1 This call balances a previous call to save(), and is used to remove all modifications to the matrix/clip state since the last save call. It is an error to call restore() more times than save() was called.

igorrmotta
  • 98
  • 4