I have a SurfaceView extension where its bones are implemented, as in the Lunar Lander example. That is, the Thread 's run() method is essentially:
public void run() { while (mRun) { Canvas c; try { c = mSurfaceHolder.lockCanvas(); synchronized (mSurfaceHolder) { doDraw(c);
And Thread will stop correctly when the surface is destroyed:
public void surfaceDestroyed(SurfaceHolder holder) { // we have to tell thread to shut down & wait for it to finish, or else // it might touch the Surface after we return and explode boolean retry = true; thread.setRunning(false); while (retry) { try { thread.join(); retry = false; } catch (InterruptedException e) { } } }
On the devices that I usually tested today (HTC Desire, Desire HD and Archos 101, which between them have OS 2.2 and 2.3.3, if I remember correctly), there were no problems with this. That is, when a surface is destroyed because the user returns from an Activity or another Activity , called from above, the code inside surfaceDestroyed() always ensures that mSurfaceHolder.lockCanvas() will never be called to return null .
The difference that I found in my new HTC One X, which is running Android 4 / ICS, however, is that when I call the surfaceDestroyed() method (i.e. the code inside this method is still running) my picture Thread will be given a null canvas from mSurfaceHolder.lockCanvas() . This, of course, will cause the application to crash. On my One X, this will happen every time the surface is destroyed - whether it is due to the phone turning, returning from Activity , etc.
I got confused about this because I got the impression that mSurfaceHolder.lockCanvas() should return a non- null Canvas until surfaceDestroyed() exits. In fact, this is what Javadok says:
This is called immediately before a surface is being destroyed. After returning from this call, you should no longer try to access this surface. If you have a rendering thread that directly accesses the surface, you must ensure that thread is no longer touching the Surface before returning from this function.
My solution for now is to just check for null . This works great:
if(c != null){ doDraw(c); // Main drawing method - not included in this code snippet }
But, any ideas why I suddenly have to do this for Android 4 / ICS?