I created an Android app which draws a small image to the screen and exits if you tap in the bottom 50px of the screen. When I tap there, it exits fine, however, when I press the back (or home) button to exit the application, it exits, but then says, "Unfortunately, Game Development has stopped." I also checked LogCat, and it showed that a Java NullPointerException occurred each time it stopped working. The output from LogCat was:
10-30 01:13:28.280: E/AndroidRuntime(15294): FATAL EXCEPTION: Thread-1718
10-30 01:13:28.280: E/AndroidRuntime(15294): java.lang.NullPointerException
10-30 01:13:28.280: E/AndroidRuntime(15294): at tricrose.gamedev.GameView.onDraw(GameView.java:56)
10-30 01:13:28.280: E/AndroidRuntime(15294): at tricrose.gamedev.GameThread.run(GameThread.java:30)
I have three Java classes: Game.java (the Activity), GameView.java (the SurfaceView), and GameThread.java (the main Thread).
The code is as follows:
Game.java:
package tricrose.gamedev;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
public class Game extends Activity {
public static final String TAG = Game.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new GameView(this));
Log.d(TAG, "View added");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_game, menu);
return true;
}
}
GameView.java:
package tricrose.gamedev;
import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
public static final String TAG = GameView.class.getSimpleName();
private GameThread thread;
public GameView(Context context) {
super(context);
getHolder().addCallback(this);
thread = new GameThread(getHolder(), this);
setFocusable(true);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (Exception e) {}
}
}
public boolean onTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
if (e.getY() > getHeight() - 60) {
thread.setRunning(false);
((Activity)getContext()).finish();
}
}
return super.onTouchEvent(e);
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);
}
}
GameThread.java:
package tricrose.gamedev;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class GameThread extends Thread {
public static final String TAG = GameThread.class.getSimpleName();
private boolean running;
private SurfaceHolder surfaceHolder;
private GameView gameView;
public GameThread(SurfaceHolder surfaceHolder, GameView gameView) {
super();
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
public void setRunning(boolean running) {
this.running = running;
}
public void run() {
Canvas canvas;
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.gameView.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
I've searched all over the internet for a solution, and I cannot find one which has actually worked, so any help is hugely appreciated.
I finally managed to find the solution! It turned out that I should have checked if the canvas was null before calling onDraw, and if it was null, then quit the application by finishing the activity. I found the solution on JavaCodeGeeks.com, where I was looking at an Android tutorial. Thanks everyone for all your answers!
why you have doing drawing from two places from onDraw and GameThread run method. I think you need to remove onDraw do every drawing from GameThread rlun method only.
This is just a guess, but your app might still be drawing while the app is trying to exit. In you onDraw method you call this line of code (which is probably your cause of problem):
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);
In that case you might not have resuorces available anymore ;)
You can try to:
1. Put a class private bitmap variable into your GameView Class:
private Bitmap mBitmap;
2. Load the bitmap in your GameView constructor:
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.droid_1);
3. Draw using the (already loaded) bitmap:
canvas.drawBitmap(mBitmap, 10, 10, null);
Hope that helps!
Related
Hello Every One I am trying to make music app in Android Studio. When I select a song in a recycler view, the song start playing in the new activity but when I go back to the songs list and select the new song both the songs start playing,I want that the previous song which was selected in the first place stop playing and new song start playing, How can I do it?
package com.recycler.hp.navigationbar;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.SeekBar;
public class Revival_Activity extends Activity implements
OnClickListener, OnTouchListener, OnCompletionListener, OnBufferingUpdateListener {
private ImageButton buttonPlayPause;
private SeekBar seekBarProgress;
String editTextSongURL;
private MediaPlayer mediaPlayer;
private int mediaFileLengthInMilliseconds; // this value contains the song duration in milliseconds. Look at getDuration() method in MediaPlayer class
private final Handler handler = new Handler();
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_revival_);
editTextSongURL=getIntent().getStringExtra("url");
initView();
}
/**
* This method initialise all the views in project
*/
#SuppressLint("ClickableViewAccessibility")
private void initView() {
buttonPlayPause = (ImageButton) findViewById(R.id.ButtonTestPlayPause);
buttonPlayPause.setOnClickListener(this);
seekBarProgress = (SeekBar) findViewById(R.id.SeekBarTestPlay);
seekBarProgress.setMax(99); // It means 100% .0-99
seekBarProgress.setOnTouchListener(this);
// editTextSongURL = getString(R.string.testsong_20_sec);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
/**
* Method which updates the SeekBar primary progress by current song playing position
*/
private void primarySeekBarProgressUpdater() {
seekBarProgress.setProgress((int) (((float) mediaPlayer.getCurrentPosition() / mediaFileLengthInMilliseconds) * 100)); // This math construction give a percentage of "was playing"/"song length"
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
primarySeekBarProgressUpdater();
}
};
handler.postDelayed(notification, 1000);
}
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.ButtonTestPlayPause) {
/** ImageButton onClick event handler. Method which start/pause mediaplayer playing */
try {
mediaPlayer.setDataSource(editTextSongURL); // setup song from http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3 URL to mediaplayer data source
mediaPlayer.prepare(); // you must call this method after setup the datasource in setDataSource method. After calling prepare() the instance of MediaPlayer starts load data from URL to internal buffer.
} catch (Exception e) {
e.printStackTrace();
}
mediaFileLengthInMilliseconds = mediaPlayer.getDuration(); // gets the song length in milliseconds from URL
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
buttonPlayPause.setImageResource(R.drawable.pause);
} else {
mediaPlayer.pause();
buttonPlayPause.setImageResource(R.drawable.play);
}
primarySeekBarProgressUpdater();
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == R.id.SeekBarTestPlay) {
/** Seekbar onTouch event handler. Method which seeks MediaPlayer to seekBar primary progress position*/
if (mediaPlayer.isPlaying()) {
SeekBar sb = (SeekBar) v;
int playPositionInMillisecconds = (mediaFileLengthInMilliseconds / 100) * sb.getProgress();
mediaPlayer.seekTo(playPositionInMillisecconds);
}
}
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
/** MediaPlayer onCompletion event handler. Method which calls then song playing is complete*/
buttonPlayPause.setImageResource(R.drawable.play);
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
/** Method which updates the SeekBar secondary progress by current song loading from URL position*/
seekBarProgress.setSecondaryProgress(percent);
}
}
It’s possible that you’re creating multiple media player objects during your selections in your recyclerview. Try creating a singleton instance of media player that’s shared throughout your app and call mediaplayer.release() and then recreate before playing a new song.
When I run my code below everything works fine. When I want to go back to the previous activity (using the emulator) I get a black screen and then the app shuts down. I also get a black screen when I exit the application and try to resume it.
The code:
package com.example.bono.as3;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.io.InputStream;
public class Main extends Activity {
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawView = new DrawView(this);
setContentView(drawView);
}
#Override public void onResume(){
super.onResume();
drawView.resume();
}
#Override public void onPause(){
super.onPause();
drawView.pause();
}
public class DrawView extends SurfaceView implements Runnable{
Thread gameloop = new Thread();
SurfaceHolder surface;
volatile boolean running = false;
AssetManager assets = null;
BitmapFactory.Options options = null;
Bitmap incect[];
int frame = 0;
public DrawView(Context context){
super(context);
surface = getHolder();
assets = context.getAssets();
options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
incect = new Bitmap[2];
try {
for (int n = 0; n < incect.length; n++){
String filename = "incect"+Integer.toString(n+1)+".png";
InputStream istream = assets.open(filename);
incect[n] = BitmapFactory.decodeStream(istream,null,options);
istream.close();
}
} catch (IOException e){
e.printStackTrace();
}
}
public void resume(){
running = true;
gameloop = new Thread(this);
gameloop.start();
}
public void pause(){
running = false;
while (true){
try {
gameloop.join();
}
catch (InterruptedException e){}
}
}
#Override public void run (){
while (running){
if (!surface.getSurface().isValid())
continue;
Canvas canvas = surface.lockCanvas();
canvas.drawColor(Color.rgb(85, 107, 47));
canvas.drawBitmap(incect[frame], 0, 0, null);
surface.unlockCanvasAndPost(canvas);
frame++;
if (frame > 1) frame = 0;
try {
Thread.sleep(500);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
I dont get any error message in the log, what I do get is about 13 messages saying "suspending all threads took: X ms" so it has something to do with my gameloop Thread I think. Unfortunately I don't see what the problem is in my code...
If you need a context, use getApplicationContext() or Activity.this. (seems less buggy with my code)
While going back to a previously used activity, onCreate() is not called, only onResume(), so it might help if you move the following lines to there.
drawView = new DrawView(this);
setContentView(drawView);
Why use inner class at all? Activity is a class already. If you want to use the code multiple times, make it a class on its own.
This is what i use to navigate back. Maybe this is usefull for you 2!
Button backpressed = (Button) findViewById(R.id.btBack);
backpressed.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onBackPressed();
}
});
The onBackPressed() is just a method that you can call if you want to return to the last page.
What it looks like for me:
I am implementing a simple render view class for Android extending SurfaceView. My main activity class includes an infinite while loop for other operations.
However, the app shows a black screen when main activity is in the infinite loop. As far as I know, main activity and surface view classes have their own separate threads, so surface view class should keep rendering even when main activity class is busy. The app works just fine when I prevent infinite loop by setting 'running' boolean variable false in the code.
What might be the reason of that surface view class stops rendering when my main activity is in an infinite loop?
My main activity and surface view classes are as follows:
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity{
RenderSurfaceView renderView;
public boolean running = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
renderView = new RenderSurfaceView(this);
setContentView(renderView);
loop();
}
public void loop(){
running = true;
while(running){
}
}
protected void onResume() {
super.onResume();
renderView.resume();
}
protected void onPause() {
super.onPause();
renderView.pause();
}
}
This my render class that extends SurfaceView:
import java.util.Random;
import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class RenderSurfaceView extends SurfaceView implements Runnable{
Thread renderThread = null;
SurfaceHolder holder;
volatile boolean running = false;
Random r = new Random();
public RenderSurfaceView(Context context) {
super(context);
holder = getHolder();
}
public void resume() {
running = true;
renderThread = new Thread(this);
renderThread.start();
}
public void run() {
while(running) {
if(!holder.getSurface().isValid())
continue;
render();
}
}
private void render(){
Canvas canvas = holder.lockCanvas();
canvas.drawRGB(r.nextInt(255), r.nextInt(255), r.nextInt(255));
holder.unlockCanvasAndPost(canvas);
}
public void pause() {
running = false;
while(true) {
try {
renderThread.join();
} catch (InterruptedException e) {
// retry
}
}
}
}
This
renderView = new RenderSurfaceView(this);
setContentView(renderView);
does not show the view immediately. Instead it has to go through a layout traversal first, which doesn't happen immediately but asynchronously to the Activity lifecycle methods, and it happens on the main thread. So running an infinite loop at the end of onCreate() prevents the layout traversal of the view hierarchy, which means your SurfaceView will never be shown.
In theory you could experiment with starting your infinite loop delayed using a Handler, for experimental purposes maybe. In general infinite loops on the main thread are a super bad idea and I can't see a reason why you would want to do this, apart from experiments maybe.
My self-answer to this question Modifying views in AsyncTask doInBackground() does not (always) throw exception has a bit more detail on what's going on behind the scenes. The question is not directly related to what you're asking here, but the background is the same I believe.
I'm having some problems with creating a SensorManager and outputting the values of the accelerometer on the screen with a green circle that moves when you tilt the phone. It's an example from Sam's teach yourself android game programming in 24 hours by Jonathan Harbour. I have checked and double checked and my code is identical to his. Basically, it's a Custom SurfaceHolder canvas that uses a Thread to repeatedly update. Here is the main activity, Game (yes, I know, the imports are messy):
package com.example.sensordemo;
import java.util.*;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.renderscript.Float2;
import android.renderscript.Float3;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
public class Game extends Activity implements SensorEventListener
{
DrawView drawView;
SensorManager sensors;
Sensor accel;
Float3 accelMotion = new Float3();
List<Sensor> sensorList;
#Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
drawView = new DrawView(this);
setContentView(drawView);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
sensors = (SensorManager) getSystemService(SENSOR_SERVICE);
accel = sensors.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorList = sensors.getSensorList(Sensor.TYPE_ALL);
Log.i("Game", "onCreate()");
}
#Override public void onSensorChanged(SensorEvent event)
{
switch (event.sensor.getType())
{
case Sensor.TYPE_ACCELEROMETER:
accelMotion.x = event.values[0];
accelMotion.y = event.values[1];
accelMotion.z = event.values[2];
break;
}
}
#Override public void onAccuracyChanged(Sensor arg0, int arg1)
{
}
#Override public void onResume()
{
super.onResume();
Log.i("Game", "resume");
drawView.resume();
sensors.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override public void onPause()
{
super.onPause();
drawView.pause();
sensors.unregisterListener(this);
Log.i("Game", "pause");
}
public class DrawView extends SurfaceView implements Runnable
{
Thread gameloop = null;
SurfaceHolder surface = null;
volatile boolean running = false;
AssetManager assets = null;
Paint paint = new Paint();
Float2 center;
public DrawView(Context context)
{
super(context);
surface = getHolder();
assets = context.getAssets();
Log.i("Game", "draw view made");
}
public void resume()
{
running = true;
gameloop = new Thread(this);
gameloop.start();
Log.i("Game", "drawview resumed");
}
public void pause()
{
running = false;
Log.i("DrawView", "pausing");
while(true)
{
try
{
gameloop.join();
}
catch(InterruptedException e)
{
}
}
}
#Override public void run()
{
while(running)
{
if(!surface.getSurface().isValid()) continue;
Canvas canvas = surface.lockCanvas();
canvas.drawColor(Color.BLACK);
Log.i("Game", "running");
float width = canvas.getWidth();
float height = canvas.getHeight();
center = new Float2(width / 2.0f, height / 2.0f);
Float2 ratio = new Float2(width / 10.0f, height / 10.0f);
float x = center.x - accelMotion.x * ratio.x;
float y = center.y + accelMotion.y * ratio.y;
paint.setColor(Color.GREEN);
canvas.drawCircle(x, y, 100, paint);
paint.setColor(Color.WHITE);
paint.setTextSize(24);
canvas.drawText("Accelerometer Demo", 10, 20, paint);
String s = "X=" + Math.round(accelMotion.x) + ", Y=" + accelMotion.y + ", Z=" + accelMotion.z;
canvas.drawText(s, 10, 50, paint);
canvas.drawText("Model: " + accel.getVendor(), 10, 80, paint);
surface.unlockCanvasAndPost(canvas);
try
{
Thread.sleep(20);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
I don't know what the problem is. The Screen goes all white and nothing happens (The thingy at the top with notifications is still visible). Also, it crashes the phone sometimes. It's a htc 1 M7 running android 5.0.1. This is the output from Logcat:
06-17 21:47:40.760: W/asset(14951): Copying FileAsset 0xb85d1e68 (zip:/data/app/com.example.sensordemo-1/base.apk:/resources.arsc) to buffer size 157568 to make it aligned.
06-17 21:47:40.770: E/Typeface(14951): SANS_LOC file not found.
06-17 21:47:40.790: I/Game(14951): draw view made
06-17 21:47:41.090: E/SensorManager(14951): uid = 10196
06-17 21:47:41.100: E/SensorManager(14951): uid = 10196
06-17 21:47:41.100: I/Game(14951): onCreate()
06-17 21:47:41.110: I/Game(14951): resume
06-17 21:47:41.110: I/Game(14951): drawview resumed
06-17 21:47:41.110: I/SensorManager(14951): registerListenerImpl: listener = com.example.sensordemo.Game#110bc638, sensor = {Sensor name="BOSCH BMA250 3-axis Accelerometer", vendor="BOSCH", version=1, type=1, maxRange=39.2266, resolution=0.038307227, power=0.1, minDelay=10000}, delay = 200000, handler = null
06-17 21:47:41.130: D/Atlas(14951): Validating map...
06-17 21:47:41.150: E/Typeface(14951): SANS_LOC file not found.
06-17 21:47:41.150: I/DrawView(14951): pausing
I would just like to note that pause is called straight away, not when I tab out of the app. Exiting and entering the app does not make the programme continue, it just stops. Nothing happens on the screen apart from it turning white, going into landscape mode and nothing else. Sorry for the long post, but I have no idea what is going on, and so I have tried to include all relevant sources. Any suggestions, ideas and, of course, any solutions you have please comment or reply below. All help is appreciated. If you require any other files I will add them, just tell me.
I'm working with the same book and had the same problem... ran across your question looking for an answer, so I thought I'd backtrack and pass along what I found (after MUCH pain and suffering lol)
The problem seems to be in the pause procedure (not the onPause, the pause in DrawView). I think it was that the thread was not properly stopped, and they tried to re-start the same thread again in the resume procedure.
After changing it to the following code, everything seems to work fine.
public void pause() {
gameloop.interrupt();
running = false;
try{
gameloop.join();
} catch (InterruptedException e) {}
}
This is a simple Android game built on one Activity that is extended in my AndroidGame class. Most of my other classes extend my 'Screen' class to make things like the Menu, In-Game screen, Game Over screen, etc. I would like to create an instance of CountDownTimer, call it once the user presses play and the game is confirmed to be running (in my GameScreen class), and then return the user to the main menu after 30 seconds are up.
My main Activity looks like this. I've included the whole class but surrounded the important parts with comments:
package com.game.framework.implementation;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Window;
import android.view.WindowManager;
import com.game.framework.Audio;
import com.game.framework.FileIO;
import com.game.framework.Game;
import com.game.framework.Graphics;
import com.game.framework.Input;
import com.game.framework.Screen;
public abstract class AndroidGame extends Activity implements Game {
AndroidFastRenderView renderView;
Graphics graphics;
Audio audio;
Input input;
FileIO fileIO;
Screen screen;
WakeLock wakeLock;
//////// Timer variables ////////
public static boolean timerFinished = false;
public static MyCount counter;
////////////////////////////////////////
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
int frameBufferWidth = isPortrait ? 480: 800;
int frameBufferHeight = isPortrait ? 800: 480;
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth, frameBufferHeight, Config.RGB_565);
float scaleX = (float) frameBufferWidth / getWindowManager().getDefaultDisplay().getWidth();
float scaleY = (float) frameBufferHeight / getWindowManager().getDefaultDisplay().getHeight();
renderView = new AndroidFastRenderView(this, frameBuffer);
graphics = new AndroidGraphics(getAssets(), frameBuffer);
fileIO = new AndroidFileIO(this);
audio = new AndroidAudio(this);
input = new AndroidInput(this, renderView, scaleX, scaleY);
screen = getInitScreen();
setContentView(renderView);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MyGame");
//////// Instantiate counter ////////
counter = new MyCount(30000,1000);
//////////////////////////////////
}
#Override
public void onResume() {
super.onResume();
wakeLock.acquire();
screen.resume();
renderView.resume();
}
#Override
public void onPause() {
super.onPause();
wakeLock.release();
renderView.pause();
screen.pause();
if (isFinishing())
screen.dispose();
}
#Override
public Input getInput() {
return input;
}
#Override
public FileIO getFileIO() {
return fileIO;
}
#Override
public Graphics getGraphics() {
return graphics;
}
#Override
public Audio getAudio() {
return audio;
}
#Override
public void setScreen(Screen screen) {
if (screen == null)
throw new IllegalArgumentException("Screen must not be null");
this.screen.pause();
this.screen.dispose();
screen.resume();
screen.update(0);
this.screen = screen;
}
#Override
public void onBackPressed() {
getCurrentScreen().backButton();
}
public Screen getCurrentScreen() {
return screen;
}
//////// The Timer Class ////////////////////////////////
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
timerFinished = true;
}
#Override
public void onTick(long millisUntilFinished) {
}
}
////////////////////////////////////////////////////////
}
Now once the timer runs out, as you see, I change the boolean timerFinished to true. In my GameScreen class I have a method called updateRunning that deals with user interaction once the game is live and running (play has been pressed).
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
///// Start the timer and go to menu if time is up /////
AndroidGame.counter.start();
if (AndroidGame.timerFinished == true) {
goToMenu();
}
///////////////////////////////////////////////////////
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = (TouchEvent) touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN) {
// Do lots of stuff based on which buttons the user presses
I am not getting an errors and the game is running fine, but it is not returning to the main menu after the 30 seconds are up. I have no idea why and would really appreciate any thoughts on the matter. Thanks!
EDIT 1: This is my goToMenu() method:
private void goToMenu() {
game.setScreen(new MainMenuScreen(game));
}
I cannot call this within AndroidGame because it references game, and making that static will cause a lot of issues.
EDIT 2:
Here's a TLDR version of what I'm trying to do - for clarity.
I have class1, where I extend Activity, and class2 where I deal with user input and paint items to the screen.
In my Android game, I want a function that will count down from 30 seconds. I want to pass the time remaining into a global variable so I can paint it in class2. Once the Timer reaches 0, I would like to run goToMenu(), which also has to exist in class2.
As of now, I have the CountDownTimer subclass in class1 and I instantiate it there. I have a global boolean that I set to True within the timer's onFinish() method. If the boolean is True, then I run goToMenu() in class2 but for some reason it does not work.