4

I have been trying to do a Draw in an Observer callback and I always get a null return when I try to lock the canvas. The SurfaceHolder seems OK. I added a SurfaceHolder callback and it gets called early in the game.

Here is my Observer update method:

// implements Observer
public void update(Observable observable, Object data) {
   Canvas c = null;
   Log.i(TAG, "Surface Observer of CbSurfaceState thread: "
         + Thread.currentThread().getName());
   try {
      synchronized(mCbHolder) {
         c = mCbHolder.lockCanvas(null);
         if(c == null) {
             Log.i(TAG, "lockCanvas returned null");
          } else {
             doDraw(c);
          }
       }
    } finally {
       // do this in a finally so that if an exception is thrown
       // during the above, we don't leave the Surface in an
       // inconsistent state
       if (c != null) {
          mCbHolder.unlockCanvasAndPost(c);
       }
    }
}

Here is where I first use it in the initialization:

public void initCbSurfaceView(Context context) {
   mContext = context;
   // register our interest in hearing about changes to our surface
   mCbHolder = getHolder();
   Log.i(TAG,"got holder");
   mCbHolder.addCallback(cbSurfaceHolderCallback);
   Log.i(TAG,"added callback");
   // initially in preview mode
   mCbHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
   // previewHolder.(SurfaceHolder); Don't know how to replace, but it
   // won't work without the above.
   ...
   mCbSurfaceState.addObserver(this);
   Log.i(TAG, "Creation of CbSurfaceState thread: "
         + Thread.currentThread().getName());
}

I even set it again when the surface is created, (I recently add that just to be sure)

SurfaceHolder.Callback cbSurfaceHolderCallback = new SurfaceHolder.Callback() {
   @Override
   public void surfaceCreated(SurfaceHolder holder) {
      Log.i(TAG, "In surfaceCreated callback");
      mCbHolder = holder;
   }
   ...
};

Here is some log. I printed the thread because at first it was starting from an Asynch thread and I managed to avoid that.:

02-24 20:31:10.380: I/CbSurfaceView(4013): In surfaceCreated callback

02-24 20:31:10.380: I/CbSurfaceView(4013): SurfaceChanged 854X404

02-24 20:31:10.380: I/CbSurfaceView(4013): initPreview width 854 height 404

...

02-24 20:31:25.974: I/CbTouchListener(4013): onTouch Down x 665.7714 y 194.92023

02-24 20:31:25.974: I/CbSurfaceView(4013): Surface Observer of CbSurfaceState thread: main

02-24 20:31:25.981: I/CbSurfaceView(4013): lockCanvas returned null

02-24 20:31:26.005: I/CbSurfaceView(4013): Surface Observer of CbSurfaceState thread: main

02-24 20:31:26.075: I/CbSurfaceView(4013): lockCanvas returned null

What in the world am I doing wrong? My doDraw was working until it got to trying to draw the bitmap. Then I thought to check for null from the lockCanvas.

I found an answer here How to draw an overlay on a SurfaceView used by Camera on Android? It seems that you can not draw on a preview. I was getting an exception about PUSH_BUFFER type surface, so I reset it to NORMAL so that it would not complain. I could not lock the surface of the preview and it would throw an exception if it was not NORMAL. Apparently you cannot change the surface type dynamically. That is probably why it is deprecated, but the camera preview will not work unless you set it to PUSH_BUFFER. I will add another, non-Surface view on top for drawing and rendering the pictures taken.

Thanks for looking and I hope this helps someone.

Community
  • 1
  • 1
  • Have toy tried lockCanvas(), without any params. I suspect since you're giving it a null rect it's decided you don't want to do any drawing. – alex Feb 25 '13 at 04:27
  • Yeah, I checked that both my Rects were what I wanted, but I was not even getting there after I added the check for null on the lockCanvas. – Patrick Moore Feb 25 '13 at 04:36

0 Answers0