Thursday, 5 October 2017

observers - android SurfaceHolder.lockCanvas returns null

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.

No comments:

Post a Comment

casting - Why wasn't Tobey Maguire in The Amazing Spider-Man? - Movies & TV

In the Spider-Man franchise, Tobey Maguire is an outstanding performer as a Spider-Man and also reprised his role in the sequels Spider-Man...