org.hermit.android.core
Class SurfaceRunner

java.lang.Object
  extended by SurfaceView
      extended by org.hermit.android.core.SurfaceRunner
Direct Known Subclasses:
InstrumentSurface

public abstract class SurfaceRunner
extends SurfaceView

Common base for applications with an animated view. This class can be used in games etc. It handles all the setup states of a SurfaceView, and provides a Thread which the app can use to manage the animation.

When using this class in an app, the app context must call these methods (usually from its corresponding Activity methods):

The surface is enabled once it is created and sized, and onStart() and onResume() have been called. You then start and stop it by calling surfaceStart() and surfaceStop().


Field Summary
static int LOOPED_TICKER
          Surface runner option: use a Looper to drive animations.
static int SURFACE_DYNAMIC
          Surface runner option: handle configuration changes dynamically.
 
Constructor Summary
SurfaceRunner(Context app)
          Create a SurfaceRunner instance.
SurfaceRunner(Context app, AttributeSet attrs)
          Create a SurfaceRunner instance.
SurfaceRunner(Context app, int options)
          Create a SurfaceRunner instance.
 
Method Summary
protected abstract  void animStart()
          We are starting the animation loop.
protected abstract  void animStop()
          We are stopping the animation loop, for example to pause the app.
protected abstract  void appSize(int width, int height, Bitmap.Config config)
          Set the screen size.
protected abstract  void appStart()
          The application is starting.
protected abstract  void appStop()
          The application is closing down.
protected abstract  void doDraw(Canvas canvas, long now)
          Draw the current frame of the application.
protected abstract  void doUpdate(long now)
          Update the state of the application for the current frame.
 Bitmap getBitmap()
          Get a Bitmap which is the same size and format as the surface.
 Bitmap getBitmap(int w, int h)
          Get a Bitmap of a given size, in the same format as the surface.
 java.lang.String getRes(int resid)
          Get the String value of a resource.
 void onPause()
          Pause the app.
 void onResume()
          We're resuming the app.
 void onStart()
          The application is starting.
 void onStop()
          The application is closing down.
 boolean onSurfaceThread()
          Determine whether the caller is on the surface's animation thread.
 void onWindowFocusChanged(boolean hasWindowFocus)
          Handle changes in focus.
 boolean optionSet(int option)
          Check whether the given option flag is set on this surface.
 void postUpdate()
          Asynchronously schedule an update; i.e.
 void setDebugPerf(boolean enable)
          Turn display of performance info on or off.
 void setDebugPos(int x, int y)
          Set the screen position at which we display performance info.
 void setDelay(long delay)
          Set the delay in ms in each iteration of the main loop.
 void statsCount(int index, int val)
          Increment a performance counter.
protected  void statsCreate(java.lang.String[] labels)
          Reserve space in the stats display for some application performance stats.
 void statsTime(int index, long val)
          Record a performance timer.
 void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
          This is called immediately after any structural changes (format or size) have been made to the surface.
 void surfaceCreated(SurfaceHolder holder)
          This is called immediately after the surface is first created.
 void surfaceDestroyed(SurfaceHolder holder)
          This is called immediately before a surface is destroyed.
 void surfaceStart()
          Start the surface running.
 void surfaceStop()
          Stop the surface running.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

SURFACE_DYNAMIC

public static final int SURFACE_DYNAMIC
Surface runner option: handle configuration changes dynamically. If set, configuration changes such as screen orientation changes will be passed up to the app; otherwise, it is assumed that we will re-start for these.

See Also:
Constant Field Values

LOOPED_TICKER

public static final int LOOPED_TICKER
Surface runner option: use a Looper to drive animations. This allows asynchronous updates to be posted by the app.

See Also:
Constant Field Values
Constructor Detail

SurfaceRunner

public SurfaceRunner(Context app)
Create a SurfaceRunner instance.

Parameters:
app - The application context we're running in.

SurfaceRunner

public SurfaceRunner(Context app,
                     int options)
Create a SurfaceRunner instance.

Parameters:
app - The application context we're running in.
options - Options for this SurfaceRunner. A bitwise OR of SURFACE_XXX constants.

SurfaceRunner

public SurfaceRunner(Context app,
                     AttributeSet attrs)
Create a SurfaceRunner instance.

Parameters:
app - The application context we're running in.
attrs - Layout attributes for this SurfaceRunner.
Method Detail

optionSet

public boolean optionSet(int option)
Check whether the given option flag is set on this surface.

Parameters:
option - The option flag to test; one of SURFACE_XXX.
Returns:
true iff the option is set.

setDelay

public void setDelay(long delay)
Set the delay in ms in each iteration of the main loop.

Parameters:
delay - The time in ms to sleep each time round the main animation loop. If zero, we will not sleep, but will run continuously.

If you want to do all your animation under direct app control using postUpdate(), just set a large delay. You may want to consider using 1000 -- i.e. one second -- to make sure you get a refresh at a decent interval.


surfaceCreated

public void surfaceCreated(SurfaceHolder holder)
This is called immediately after the surface is first created. Implementations of this should start up whatever rendering code they desire. Note that only one thread can ever draw into a Surface, so you should not draw into the Surface here if your normal rendering will be in another thread.

Parameters:
holder - The SurfaceHolder whose surface is being created.

surfaceChanged

public void surfaceChanged(SurfaceHolder holder,
                           int format,
                           int width,
                           int height)
This is called immediately after any structural changes (format or size) have been made to the surface. This method is always called at least once, after surfaceCreated(SurfaceHolder).

Parameters:
holder - The SurfaceHolder whose surface has changed.
format - The new PixelFormat of the surface.
width - The new width of the surface.
height - The new height of the surface.

surfaceDestroyed

public void surfaceDestroyed(SurfaceHolder holder)
This is called immediately before a surface is 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.

Parameters:
holder - The SurfaceHolder whose surface is being destroyed.

onStart

public void onStart()
The application is starting. Applications must call this from their Activity.onStart() method.


onResume

public void onResume()
We're resuming the app. Applications must call this from their Activity.onResume() method.


surfaceStart

public void surfaceStart()
Start the surface running. Applications must call this to set the surface going. They may use this to implement their own level of start/stop control, for example to implement a "pause" button.


surfaceStop

public void surfaceStop()
Stop the surface running. Applications may call this to stop the surface running. They may use this to implement their own level of start/stop control, for example to implement a "pause" button.


onPause

public void onPause()
Pause the app. Applications must call this from their Activity.onPause() method.


onStop

public void onStop()
The application is closing down. Applications must call this from their Activity.onStop() method.


onWindowFocusChanged

public void onWindowFocusChanged(boolean hasWindowFocus)
Handle changes in focus. When we lose focus, pause the game so a popup (like the menu) doesn't cause havoc.

Parameters:
hasWindowFocus - True iff we have focus.

postUpdate

public void postUpdate()
Asynchronously schedule an update; i.e. a frame of animation. This can only be called if the SurfaceRunner was created with the option LOOPED_TICKER.


appStart

protected abstract void appStart()
The application is starting. Perform any initial set-up prior to starting the application. We may not have a screen size yet, so this is not a good place to allocate resources which depend on that.


appSize

protected abstract void appSize(int width,
                                int height,
                                Bitmap.Config config)
Set the screen size. This is guaranteed to be called before animStart(), but perhaps not before appStart().

Parameters:
width - The new width of the surface.
height - The new height of the surface.
config - The pixel format of the surface.

animStart

protected abstract void animStart()
We are starting the animation loop. The screen size is known.

doUpdate() and doDraw() may be called from this point on.


animStop

protected abstract void animStop()
We are stopping the animation loop, for example to pause the app.

doUpdate() and doDraw() will not be called from this point on.


appStop

protected abstract void appStop()
The application is closing down. Clean up any resources.


doUpdate

protected abstract void doUpdate(long now)
Update the state of the application for the current frame.

Applications must override this, and can use it to update for example the physics of a game. This may be a no-op in some cases.

doDraw() will always be called after this method is called; however, the converse is not true, as we sometimes need to draw just to update the screen. Hence this method is useful for updates which are dependent on time rather than frames.

Parameters:
now - Current time in ms.

doDraw

protected abstract void doDraw(Canvas canvas,
                               long now)
Draw the current frame of the application.

Applications must override this, and are expected to draw the entire screen into the provided canvas.

This method will always be called after a call to doUpdate(), and also when the screen needs to be re-drawn.

Parameters:
canvas - The Canvas to draw into.
now - Current time in ms. Will be the same as that passed to doUpdate(), if there was a preceeding call to doUpdate().

getRes

public java.lang.String getRes(int resid)
Get the String value of a resource.

Parameters:
resid - The ID of the resource we want.
Returns:
The resource value.

getBitmap

public Bitmap getBitmap()
Get a Bitmap which is the same size and format as the surface. This can be used to get an off-screen rendering buffer, for example.

Returns:
A Bitmap which is the same size and pixel format as the screen.

getBitmap

public Bitmap getBitmap(int w,
                        int h)
Get a Bitmap of a given size, in the same format as the surface. This can be used to get an off-screen rendering buffer, for example.

Parameters:
w - Desired width in pixels.
h - Desired height in pixels.
Returns:
A Bitmap which is the same size and pixel format as the screen.

onSurfaceThread

public boolean onSurfaceThread()
Determine whether the caller is on the surface's animation thread.

Returns:
The resource value.

setDebugPerf

public void setDebugPerf(boolean enable)
Turn display of performance info on or off.

Parameters:
enable - True to enable performance display.

setDebugPos

public void setDebugPos(int x,
                        int y)
Set the screen position at which we display performance info.

Parameters:
x - Screen X position.
y - Screen Y position.

statsCreate

protected void statsCreate(java.lang.String[] labels)
Reserve space in the stats display for some application performance stats. The given labels will become stats which will be displayed if setDebugPerf(boolean enable) is passed true. Each stat is subsequently referred to by its index in this labels array.

This method must be called before appStart() in order for the app's stats to be displayed. After appStart() is called, the stats content is frozen until the next appStop() / appStart(). Typically the app should invoke this method from its constructor. However this method is, of course, optional.

Parameters:
labels - Labels for the app's stats, one label per stat. Labels need to be 7 chars or less.

statsCount

public void statsCount(int index,
                       int val)
Increment a performance counter. This method is used for counts of specific quantities, which will be displayed as counts per second; for example frames per second.

Parameters:
index - Index of the stat to bump (its index in the "labels" argument to statsCreate(String[] labels)).
val - Amount to add to the counter.

statsTime

public void statsTime(int index,
                      long val)
Record a performance timer. This method is used for timings of specific activities; the average of the recorded values will be displayed.

Parameters:
index - Index of the stat to record (its index in the "labels" argument to statsCreate(String[] labels)).
val - The time value for this iteration.