Note that there are some explanatory texts on larger screens.

plurals
  1. POForce close on resuming an app using SurfaceView
    primarykey
    data
    text
    <p>First, note that exactly the same thing happens with the LunarLander example. Anyways, this works great until I leave the app and try to return to it, whereupon I get a force close (IllegalThreadStateException).</p> <p>MainGameActivity:</p> <pre><code>package com.tests.testgame1; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class MainGameActivity extends Activity { private static MainGameView mainGameView; //private static Thread mainGameThread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainGameView = new MainGameView(getApplicationContext()); //mainGameThread = mainGameView.getThread(); // if (savedInstanceState == null) { // // we were just launched: set up a new game // mainGameThread.setState(mainGameThread.STATE_READY); // Log.w(this.getClass().getName(), "SIS is null"); // } else { // // we are being restored: resume a previous game // mainGameThread.restoreState(savedInstanceState); // Log.w(this.getClass().getName(), "SIS is nonnull"); // } setContentView(mainGameView); } @Override protected void onStart() { super.onStart(); // The activity is about to become visible. } @Override protected void onResume() { super.onResume(); mainGameView.unpauseGame(); // The activity has become visible (it is now "resumed"). } @Override protected void onPause() { super.onPause(); mainGameView.pauseGame(); // Another activity is taking focus (this activity is about to be "paused"). } @Override protected void onStop() { super.onStop(); // The activity is no longer visible (it is now "stopped") } @Override protected void onDestroy() { super.onDestroy(); // The activity is about to be destroyed. } @Override protected void onSaveInstanceState(Bundle outState) { // just have the View's thread save its state into our Bundle super.onSaveInstanceState(outState); // mainGameThread.saveState(outState); Log.w(this.getClass().getName(), "SIS called"); } } </code></pre> <p>MainGameView:</p> <pre><code>package com.tests.testgame1; import android.content.Context; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; public class MainGameView extends SurfaceView implements SurfaceHolder.Callback { private static final String TAG = "MainGameView"; // MainGameThread mainGameThread; // SurfaceHolder mainSurfaceHolder; Context mainContext; public MainGameView(Context context) { super(context); mainSurfaceHolder = getHolder(); mainSurfaceHolder.addCallback(this); mainContext = context; mainGameThread = new MainGameThread(this, mainSurfaceHolder, mainContext); Log.d(TAG, "View created"); } public Thread getThread() { return mainGameThread; } public void pauseGame() { mainGameThread.pauseGame(); } public void unpauseGame() { //mainGameThread.start(); mainGameThread.unpauseGame(); } // @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (!hasWindowFocus) mainGameThread.pauseGame(); } public void onDraw() { } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder arg0) { mainGameThread.setRunning(true); mainGameThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { // we have to tell thread to shut down &amp; wait for it to finish, or else // it might touch the Surface after we return and explode boolean retry = true; mainGameThread.setRunning(false); while (retry) { try { mainGameThread.join(); retry = false; } catch (InterruptedException e) { } } } } </code></pre> <p>MainGameThread:</p> <pre><code>package com.tests.testgame1; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.util.Log; import android.view.SurfaceHolder; import android.view.View; class MainGameThread extends Thread { enum GameStates { GameStateRunning, GameStatePaused } private boolean running; private GameStates gameMode; private View view; private Context context; private SurfaceHolder surfaceHolder; Bitmap backgroundImage; public MainGameThread(View _view, SurfaceHolder _surfaceHolder, Context _context) { this.view = _view; this.surfaceHolder = _surfaceHolder; this.context = _context; this.running = true; this.gameMode = GameStates.GameStateRunning; Resources res = context.getResources(); backgroundImage = BitmapFactory.decodeResource(res, R.drawable.background); } public void setRunning(boolean b) { running = b; } @Override public void run() { while (running) { if (gameMode == GameStates.GameStateRunning) doStep(); Canvas c = null; try { c = surfaceHolder.lockCanvas(null); synchronized (surfaceHolder) { 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) { synchronized (surfaceHolder) { surfaceHolder.unlockCanvasAndPost(c); } } } } } private void doDraw(Canvas canvas) { canvas.drawBitmap(backgroundImage, 0, 0, null); //canvas.drawColor(Color.BLUE); } private void doStep() { } public void pauseGame() { // synchronized (surfaceHolder) { if (gameMode == GameStates.GameStateRunning){ gameMode = GameStates.GameStatePaused; } } } public void unpauseGame() { synchronized (surfaceHolder) { if (gameMode == GameStates.GameStatePaused){ gameMode = GameStates.GameStateRunning; } } } } </code></pre> <p>Stack trace:</p> <pre><code>Test Game [Android Application] DalvikVM[localhost:8625] Thread [&lt;1&gt; main] (Suspended (exception IllegalThreadStateException)) MainGameView(SurfaceView).updateWindow(boolean) line: 545 MainGameView(SurfaceView).onWindowVisibilityChanged(int) line: 206 MainGameView(View).dispatchWindowVisibilityChanged(int) line: 3891 FrameLayout(ViewGroup).dispatchWindowVisibilityChanged(int) line: 719 LinearLayout(ViewGroup).dispatchWindowVisibilityChanged(int) line: 719 PhoneWindow$DecorView(ViewGroup).dispatchWindowVisibilityChanged(int) line: 719 ViewRoot.performTraversals() line: 744 ViewRoot.handleMessage(Message) line: 1727 ViewRoot(Handler).dispatchMessage(Message) line: 99 Looper.loop() line: 123 ActivityThread.main(String[]) line: 4627 Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] Method.invoke(Object, Object...) line: 521 ZygoteInit$MethodAndArgsCaller.run() line: 868 ZygoteInit.main(String[]) line: 626 NativeStart.main(String[]) line: not available [native method] Thread [&lt;6&gt; Binder Thread #2] (Running) Thread [&lt;5&gt; Binder Thread #1] (Running) Thread [&lt;7&gt; Binder Thread #3] (Running) </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload