Reputation: 534
I am developing an Android game engine using a SurfaceView to draw Bitmaps on, with a similar framework to LunarLander. My main game engine activity sets up the layout such that it should display a SurfaceView extension class, as shown below:
super.onCreate(savedInstanceState);
setContentView(R.layout.ss_layout);
SSSurfaceView ssSurfaceView = (SSSurfaceView)findViewById(R.id.surface_view);
SSSurfaceView.SSViewThread renderThread =
(SSSurfaceView.SSViewThread) ssSurfaceView.getThread();
The findViewById method successfully returns an instance of my SurfaceView extension class, and I am able to run the thread I define within the class, which is created in this method, the class constructor:
public SSSurfaceView(Context context, AttributeSet attributes)
{
super(context, attributes);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new SSViewThread(holder, context);
}
The constructor should be obtaining a reference to the associated SurfaceHolder, which it then passes on to the thread constructor. I began having an issue inside the thread run method where holder.lockCanvas(null) was returning null. I read somewhere that this could mean that the surface has not been created, so I added an if statement using a boolean that I set to true in the surfaceCreated callback.
public void run()
{
Canvas canvas = null;
try
{
canvas = holder.lockCanvas(null);
//I added the condition below
if(surfaceCreated)
{
drawAll(canvas);
}
}
catch(Exception e)
{
Log.wtf("SurfaceView", "exception");
}
finally
{
if(canvas != null)
{
holder.unlockCanvasAndPost(canvas);
}
}
}
And here is the callback:
public void surfaceCreated(SurfaceHolder holder)
{
surfaceCreated = true;
}
And as it turns out, surfaceCreated is never called. My application displays a gray screen and does nothing else, as the drawAll method is never iterated. Here is the layout.xml file to boot:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.bostonwalker.sseng.SSSurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
EDIT: This isn't my entire code, I tried to limit my examples to the relevant sections. The thread is called in a main loop, but given time, the callback never fires.
EDIT: Here is the loop iterated in the UI thread:
while(!halt)
{
//EDIT: Changed from .run() to .start()
renderThread.start();
gameThread.start();
//Wait for both threads to proceed before continuing
try
{
renderThread.join();
gameThread.join();
}
catch (InterruptedException e)
{
//Do nothing
}
Thread.currentThread();
try
{
Thread.sleep(2);
}
catch (Exception e)
{
//Do nothing
}
}
Upvotes: 0
Views: 3639
Reputation: 30088
Your drawing thread doesn't loop - it just runs once and exits. And it's likely that the surface isn't created yet on that first run.
You'll need to put the code that you currently have in some sort of loop, such as (in pseudo-code) :
while(!done) {
lockTheCanvas();
drawAFrame();
unlockTheCanvas();
sleep(FRAME_INTERVAL);
}
You then need to terminate the thread at the appropriate time by setting "done" to true; Note that you need the sleep(), otherwise, your thread will hog the cpu, and will never terminate.
Upvotes: 1