title: Surfaceview Skeleton Tutorial questions
body: <p>After searching google, various android blogs, various game dev blogs, and other tutorial sites for surfaceviews in android I'm looking to get a complete understanding of surfaceviews.  I've read several books on Safaribooks about android and surface views, but they provide either too little information, or use other SDKs such as AndEngine.  I was hoping to learn strictly surface view.  I've played with the Lunar Lander sample project as well as other projects I've found and have created some code of a skeleton surfaceview.  It consists of 3 classes just for the skeleton.  </p>
  
  <p>The MainActivity class:</p>
  
  <pre><code>package com.learning.svlearning;
  
  import android.os.Bundle;
  import android.app.Activity;
  import android.view.Menu;
  import android.view.Window;
  import android.view.WindowManager;
  
  public class MainActivity extends Activity {
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
      //Set FullScreen Mode - No title bars!!
          requestWindowFeature(Window.FEATURE_NO_TITLE);
          getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
          // Screen created with pure java - Say no to xml (atleast for this demo)
          setContentView(new MainGamePanel(this));
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.layout_game_window, menu);
          return true;
      }
  }
  </code></pre>
  
  <p>This class is pretty straight forward.  The main game activity window, requesting full screen with no title bars.  How a real game should be :) This class calls our next class for the view by passing "this" (MainActivity) class's context.</p>
  
  <p>MainGamePanel class:</p>
  
  <pre><code>package com.learning.svlearning;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.util.Log;
  import android.view.SurfaceHolder;
  import android.view.SurfaceView;
  
  public class MainGamePanel extends SurfaceView {
  final static public String tag = "Tracer";
  
  private GameThread gameThread;  // For our thread needed to do logical processing without holding up the UI thread
  private SurfaceHolder holder; // For our CallBacks.. (One of the areas I don't understand!)
  
  public MainGamePanel(Context context) {
      super(context);
      Log.d(tag, "Inside MainGamePanel");
      gameThread = new GameThread(this); //Create the GameThread instance for our logical processing
      holder = getHolder();
  
  
      holder.addCallback(new SurfaceHolder.Callback() {
  
  
  // Since we are using the SurfaceView, we need to use, at very least, the surfaceDestroyed and surfaceCreated methods.
          @Override
          public void surfaceDestroyed(SurfaceHolder holder) {
              boolean retry = true;
              Log.d(tag, "Inside SurfaceHolder Callback - surfaceDestroyed");
              gameThread.setRunning(false); // Stop the Thread from running because the surface was destroyed.  Can't play a game with no surface!!  
  
              while (retry) { 
                  try {
                      Log.d(tag, "Inside SurfaceHolder Callback - surfaceDestroyed - while statement");
                      gameThread.join();
                      retry = false; //Loop until game thread is done, making sure the thread is taken care of.
                  } catch (InterruptedException e) {
                      //  In case of catastrophic failure catch error!!!
                  }
              }
  
          }
  
          @Override
          public void surfaceCreated(SurfaceHolder holder) {
              // let there be Surface!
              Log.d(tag, "Inside SurfaceHolder Callback - surfaceCreated");
              gameThread.setRunning(true); // Now we start the thread
              gameThread.start(); // and begin our game's logical processing
  
          }
  
          @Override
          public void surfaceChanged(SurfaceHolder holder, int format,
                  int width, int height) {
              // The code to resize the screen ratio when it flips from landscape to portrait and vice versa
  
          }
      });
  }
  
  @Override
  protected void onDraw(Canvas canvas) {
  //This is where we draw stuff..  since this is just a skeleton demo, we only draw the color Dark Grey so we can visibly see that we actually accomplished something with the surfaceview drawing
      Log.d(tag, "Inside onDraw"); 
      canvas.drawColor(Color.DKGRAY); // You can change the Color to whatever color you want, for this demo I just used Color.DKGRAY 
  
      }
  
  }
  </code></pre>
  
  <p>This class mainly deals with the drawing of our resources/images with the onDraw method, handling what happens when our surface is created and destroyed (also when the screen changes, but i didnt write any code to handle it for now), and calls our GameThread class which handles the processing of our game logic.</p>
  
  <p>GameThread class:</p>
  
  <pre><code>package com.learning.svlearning;
  
  import android.graphics.Canvas;
  import android.util.Log;
  
  
  
  public class GameThread extends Thread{
  final static public String tag = "Tracer";
  
  
  private MainGamePanel view; 
  private boolean running = false;
  
  static final long FPS = 30; // To help limit the FPS when we draw, otherwise we would kill the CPU and increase the Battery Consumption.
  
  public GameThread(MainGamePanel view){
      Log.d(tag, "inside GameThread");
      this.view = view;
  }
  
  public void setRunning(boolean run){
      Log.d(tag, "inside GameThread - setRunning");
      running = run; // For starting / stoping our game thread
  }
  
  
  @Override
  public void run() {
      long ticksPS = 1000 / FPS; // Limit the frames per second
      long startTime; 
      long sleepTime;
      Log.d(tag, "inside GameThread - run");
  
      while(running){ // Our Main Game Loop is right here
          Canvas c = null; // build our canvas to draw on
          Log.d(tag, "inside GameThread - run - while loop");
          startTime = System.currentTimeMillis(); //get the current time in milliseconds - this is for helping us limit the FPS
          try{
              c = view.getHolder().lockCanvas(); //Before we can draw, we always have to lock the canvas, otherwise goblins will invade your app and destroy everything!
              synchronized (view.getHolder()){ // we have to synchronize this because we need to make sure that the method runs when at the proper time.
                  view.onDraw(c); // this is where we pass our drawing information.  The canvas gets passed to the onDraw method in our MainGamePanel class.
              }
          }finally{
              if(c != null) {
                  view.getHolder().unlockCanvasAndPost(c); // Once we are done drawing, we unlock our canvas and post.  which means we drew on the canvas, and now the devices screen will display our drawing.
              }
          }
          sleepTime = ticksPS-(System.currentTimeMillis() - startTime); // this is where we calculace how long we need this thread to sleep (again with the FPS) we want it limited to 30 FPS as defined in our FPS variable.
          try {
              if (sleepTime &gt; 0){
                     sleep(sleepTime); // night night, sleep to limit the fps and save our batteries!
              }
              else{
                     sleep(10); // Incase something goes crazy, we still want to sleep the thread to save the battery.
              }
          }catch(Exception e){
  
          }
  
      }
  
  }
  
  
  }
  </code></pre>
  
  <p>This class deals with processing game logic and sending any drawable information to our draw method in the MainGamePanel class.  Such as if we had a character moving, we could send the x and y coordinate to our draw method to draw our character in a different position.</p>
  
  <p>Now some parts of these classes I don't really understand fully.  Like the callback, When reading the information on the googles android developers page, i'm just left more confused on what it is and why we use it.  Also, if anyone has anything more to put into this, or sees anything I may have mis-understood, feel free to correct me.  I enjoy working with android, though it is pretty difficult, when you start to figure things out, it is very rewarding!  </p>