I'm working on a game, and have come across a rather unusual problem. My game crashes when it pauses on the way to the lock screen, but works fine (pausing and resuming) when the home button is hit. I have not hard coded any long pauses where the state is saved, the whole premise that I'm working on now is a short pause like minimizing a game and returning to it. Even more unusual is that the main code I'm using works perfectly for small demos. My issues may be caused by the fact that the game is significantly larger than any demo. The code is below, along with the LogCat error that is displayed when I lock it. I'd appreciate any ideas. I'm quite stuck. Thanks.
Note, the nice people on StackOverflow said that me issue was:
You should probably not synchronize on the thread variable (doing that in surfaceDestroyed). It's set to null elsewhere (in destroy).
Actually, in general, it's always a bad idea to synchronize on a non final object reference.
However when I followed that advice my game started to crash every time the home button was hit. It would be there when you unlocked the phone, but it always started fresh. The state was not preserved.
MainGamePanel.java
- Code: Select all
public void pause() {
mSensorManager.unregisterListener(this);
}
public void resume(Context context) {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
}
public void destroy() {
thread.setRunning(false);
if (thread != null)
{
Thread killThread = thread;
thread = null;
killThread.interrupt();
}
}
Main Activity:
- Code: Select all
//Restarts the accelerometer after onPause
protected void onResume() {
super.onResume();
viewPanel.resume(this);
}
//Standard Method run when the Application loses focus.
//This runs the pause() function in the viewPanel so that
//the accelerometer can be paused.
protected void onPause() {
super.onPause();
viewPanel.pause();
}
protected void onDestroy() {
super.onDestroy();
viewPanel.destroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
viewPanel.backHit();
return true;
}
return super.onKeyDown(keyCode, event);
}
And my MainThread.java file:
- Code: Select all
public class MainThread extends Thread {
private SurfaceHolder surfaceHolder;
private MainGamePanel gamePanel;
private boolean running;
public boolean pleaseWait = true;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
@Override
public void run()
{
Canvas canvas;
Matrix matrix = new Matrix();
matrix.preScale(gamePanel.getScaleX(), gamePanel.getScaleY());
long startTime, elapsedTime;
startTime = System.currentTimeMillis();
elapsedTime = System.currentTimeMillis() - startTime;
while (running) {
if(!pleaseWait) {
canvas = null;
// try locking the canvas for exclusive pixel editing on the surface
try {
canvas = this.surfaceHolder.lockCanvas();
canvas.setMatrix(matrix);
synchronized (surfaceHolder) {
// update game state
startTime = System.currentTimeMillis();
this.gamePanel.update(elapsedTime);
// draws the canvas on the panel
this.gamePanel.onDraw(canvas);
elapsedTime = System.currentTimeMillis() - startTime;
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
else {
synchronized (this) {
try {
wait();
} catch (Exception e) { }
}
}
}
}
}
LogCat error:
- Code: Select all
06-07 15:56:45.852: E/AndroidRuntime(3374): FATAL EXCEPTION: main
06-07 15:56:45.852: E/AndroidRuntime(3374): java.lang.NullPointerException
06-07 15:56:45.852: E/AndroidRuntime(3374): at com.petronicarts.stormthecastle.MainGamePanel.surfaceDestroyed(MainGamePanel.java:312)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:600)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.SurfaceView.updateWindow(SurfaceView.java:486)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:213)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.View.dispatchDetachedFromWindow(View.java:6232)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1248)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.ViewRoot.dispatchDetachedFromWindow(ViewRoot.java:1868)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.ViewRoot.doDie(ViewRoot.java:2958)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.ViewRoot.die(ViewRoot.java:2928)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:254)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.view.Window$LocalWindowManager.removeViewImmediate(Window.java:445)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3201)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3306)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.app.ActivityThread.access$1600(ActivityThread.java:132)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1055)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.os.Handler.dispatchMessage(Handler.java:99)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.os.Looper.loop(Looper.java:150)
06-07 15:56:45.852: E/AndroidRuntime(3374): at android.app.ActivityThread.main(ActivityThread.java:4312)
06-07 15:56:45.852: E/AndroidRuntime(3374): at java.lang.reflect.Method.invokeNative(Native Method)
06-07 15:56:45.852: E/AndroidRuntime(3374): at java.lang.reflect.Method.invoke(Method.java:507)
06-07 15:56:45.852: E/AndroidRuntime(3374): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
06-07 15:56:45.852: E/AndroidRuntime(3374): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
06-07 15:56:45.852: E/AndroidRuntime(3374): at dalvik.system.NativeStart.main(Native Method)


