I've got a menu activity and a game activity which is launched from the menu. Some (most) of the times I launch the game activity; all input hangs for a few (up to 10-ish) seconds and then plays out in hyperspeed while i get this in logcat:
11-20 18:24:27.873: WARN/WindowManager(2473): Key dispatching timed out sending to southgrove.game/southgrove.game.Game
11-20 18:24:27.873: WARN/WindowManager(2473): Previous dispatch state: {{KeyEvent{action=1 code=4 repeat=0 meta=0 scancode=28 mFlags=8} to Window{4866c7a0 southgrove.game/southgrove.game.Game paused=false} @ 1290273811209 lw=Window{4866c7a0 southgrove.game/southgrove.game.Game paused=false} lb=android.os.BinderProxy@484e8a58 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4866c7a0 southgrove.game/southgrove.game.Game paused=false}}}
11-20 18:24:27.873: WARN/WindowManager(2473): Current dispatch state: {{null to Window{4833d500 southgrove.game/southgrove.game.Game paused=false} @ 1290273867876 lw=Window{4833d500 southgrove.game/southgrove.game.Game paused=false} lb=android.os.BinderProxy@485487b0 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4833d500 southgrove.game/southgrove.game.Game paused=false}}}
The menu activity:
package southgrove.game;
import southgrove.game.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class Menu extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
View playButton = findViewById(R.id.play);
playButton.setOnClickListener(new OnClickListener()
{
public void onClick(View view)
{
startActivityForResult(new Intent(Menu.this, Game.class), 0);
}
});
View testButton = findViewById(R.id.test);
testButton.setOnClickListener(new OnClickListener()
{
public void onClick(View view)
{
startActivityForResult(new Intent(Menu.this, Test.class), 0);
}
});
View closeButton = findViewById(R.id.close);
closeButton.setOnClickListener(new OnClickListener()
{
public void onClick(View view)
{
showDialog(QUIT_DIALOG);
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
showDialog(QUIT_DIALOG);
}
return super.onKeyDown(keyCode, event);
}
@Override
protected Dialog onCreateDialog(int id)
{
Dialog dialog;
switch (id)
{
case QUIT_DIALOG:
AlertDialog.Builder quitDialogBuilder = new AlertDialog.Builder(this);
quitDialogBuilder.setMessage("Exit the game?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
Menu.this.finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
dialog = quitDialogBuilder.create();
break;
default:
dialog = null;
}
return dialog;
}
private final int QUIT_DIALOG = 0;
}
The game activity:
package southgrove.game;
import southgrove.droidgl.DroidGL;
import southgrove.droidgl.core.Camera;
import southgrove.droidgl.core.Node;
import southgrove.droidgl.core.RootNode;
import southgrove.game.R;
import southgrove.game.board.BoardBase;
import southgrove.game.board.core.*;
import southgrove.game.cameras.StupidCamera;
import southgrove.input.OnTouchFilter;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.widget.TextView;
public class Game extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
// Get fpsTextView reference
fpsTextView = (TextView) findViewById(R.id.fpsTextView);
// Build meshes
TetrominoMesh.buildMeshes();
// Setup the DroidGL surface
droidgl = (DroidGL) findViewById(R.id.droidGL);
droidgl.setLongClickable(true);
droidgl.setOnTouchListener(new GameSurfaceOnTouchFilter(false));
// Create and add camera
final Camera camera = new StupidCamera();
camera.move(0, 0, 14);
droidgl.registerCamera(camera);
DroidGL.setActiveCamera(camera);
// Create and add root node
final Node rootNode = new RootNode();
droidgl.setRootNode(rootNode);
// Create and add game board
gameBoard = new GameBoard(droidgl, 32, 32, 8);
rootNode.addChild(gameBoard);
// start up updateHandler
updateHandler = new UpdateHandler();
updateHandler.sleep(1);
// get vibrator service
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
}
@Override
public void onBackPressed()
{
showDialog(QUIT_DIALOG);
}
@Override
protected Dialog onCreateDialog(int id)
{
Dialog dialog;
switch (id)
{
case QUIT_DIALOG:
AlertDialog.Builder quitDialogBuilder = new AlertDialog.Builder(this);
quitDialogBuilder.setMessage("Really quit?")
.setCancelable(false)
.setPositiveButton("Yup!", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
Game.this.finish();
}
})
.setNegativeButton("Nope!", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
dialog = quitDialogBuilder.create();
break;
default:
dialog = null;
}
return dialog;
}
@Override
protected void onPause()
{
super.onPause();
droidgl.onPause();
}
protected void onUpdate()
{
fpsTextView.setText("fps: " + String.valueOf(droidgl.getFps()));
updateHandler.sleep(500);
}
@Override
protected void onResume()
{
super.onResume();
droidgl.onResume();
}
private DroidGL droidgl;
private GameBoard gameBoard;
private TextView fpsTextView;
private Vibrator vibrator;
private UpdateHandler updateHandler;
private final int QUIT_DIALOG = 0;
private class UpdateHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
Game.this.onUpdate();
}
public void sleep(long delayMillis)
{
this.removeMessages(0);
if (!Game.this.isFinishing())
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
private class GameSurfaceOnTouchFilter extends OnTouchFilter
{
public GameSurfaceOnTouchFilter(Boolean consumeEvent)
{
super(consumeEvent);
}
private float flipDeltaX;
private float flipDeltaY;
protected void doubleTap(float x, float y)
{
super.doubleTap(x, y);
synchronized (gameBoard)
{
if (gameBoard.dropCursorTetromino())
{
gameBoard.resetReactorTimer();
gameBoard.setCursorTetromino((int) (Tetromino.NUM_TYPES * Math.random() - 1), 0);
if (gameBoard.removeConnectedTetrominoes(3))
{
gameBoard.startShockWave(0, 0, 10f, 0.35f);
vibrator.vibrate(300);
} else
{
vibrator.vibrate(50);
}
}
}
}
protected void down(int pointer, float x, float y)
{
super.down(pointer, x, y);
if (pointer == 0)
{
}
if (pointer == 1)
{
flipDeltaX = 0;
flipDeltaY = 0;
}
}
protected void up(int pointer, float x, float y)
{
super.up(pointer, x, y);
synchronized (gameBoard)
{
}
}
protected void move(int pointer, float x, float y, float dx, float dy)
{
super.move(pointer, x, y, dx, dy);
synchronized (gameBoard)
{
if (pointer == 0)
{
gameBoard.addInertia(-dx * 0.0045f, dy * 0.0045f);
}
if (pointer == 1)
{
flipDeltaX -= dx;
flipDeltaY += dy;
if (Math.abs(flipDeltaX) > 45 || Math.abs(flipDeltaY) > 45)
{
vibrator.vibrate(50);
if (Math.abs(flipDeltaX) > Math.abs(flipDeltaY))
{
if (flipDeltaX > 0)
{
gameBoard.rotateCursorTetromino(1);
} else
{
gameBoard.rotateCursorTetromino(-1);
}
} else
{
if (flipDeltaY > 0)
{
gameBoard.rotateCursorTetromino(1);
} else
{
gameBoard.rotateCursorTetromino(-1);
}
}
flipDeltaX = 0;
flipDeltaY = 0;
}
}
}
}
}
private class GameBoard extends BoardBase
{
public GameBoard(DroidGL droidGL, int width, int height, int depth)
{
super(droidGL, width, height, depth);
}
public void resetReactorTimer()
{
synchronized (this)
{
reactorTimer = 0;
}
}
public void startShockWave(int gridPosX, int gridPosY, float length, float magnitude)
{
synchronized (this)
{
for (int i = 0; i < tetrominoes.size(); i++)
{
tetrominoes.get(i).bounce(
(float) (Math.random() * 0.12f),
(float) (Math.random() * magnitude)
);
}
}
}
@Override
protected void onSetup()
{
synchronized (this)
{
setCursorTetromino((int) (Tetromino.NUM_TYPES * Math.random()), 0);
for (int i = 0; i < 1024; i++)
{
addTetromino(
(int) (Math.random() * Tetromino.NUM_TYPES),
(int) (Math.random() * width / 2) * 2,
(int) (Math.random() * height / 2) * 2,
(int) (Math.random() * 2),
(int) (Math.random() * 4));
}
removeConnectedTetrominoes(3);
}
}
@Override
protected void onLogic(float timeFactor)
{
synchronized (this)
{
if (shiftTimer > shiftTime || tetrominoes.size() < 15)
{
shiftTimer = 0;
shiftTime -= shiftTime / 5;
shiftUp();
for (int i = 0; i < 256; i++)
{
addTetromino(
(int) (Math.random() * Tetromino.NUM_TYPES),
(int) (Math.random() * width / 2) * 2,
(int) (Math.random() * height / 2) * 2,
0,// (int) (Math.random() * (depth - 1)),
(int) (Math.random() * 4));
}
}
if (reactorTimer > 1f)
{
reactorTimer = 0;
drop();
removeConnectedTetrominoes(3);
}
reactorTimer += timeFactor;
shiftTimer += timeFactor;
}
}
private float shiftTime = 60 * 5;
private float reactorTimer;
private float shiftTimer;
}
}
What could be causing this? Any ideas/speculations are welcome. And yes, I know that's a pretty massive wall of code to sift through.