my class MainActivity starts the Activity "GameActivity" by user interaction (button). My class GameView is the view for my class GameActivity and has an implementation of the Runnable interface. Inside I've implemented a Handler as timer, that runs the trigger() method continuously. When gameIsOver == true the game stops and starts the GameOverActivity. Inside the GameOverActivity I've added a Button to commit the score. If you press the Button you get back to the MainView and you can start a new game.
Now to the problem: After I've played the game the GameOverActivity gets started, I commit the score and start a new Game or I end the Game and exit (not kill) the app.
In both ways, sometimes the GameOverActivity starts again and shows me that the Game is over. How could that be? Where is it called from? I guess the timer or the Runnable wasn't stopped correctly, but I really don't know what to do to prevent that problem...
PS: If the GameOverActivity gets started during the game, the game doesn't really end. If I press the back button on my phone, I'm just back in game.
GameView.java
private Handler timerHandler;
private boolean gameIsOver;
private long triggerTime, counter;
public void init() {
gameIsOver = false;
triggerTime = 1000;
counter = 0;
timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (gameIsOver) {
return;
}
long millis = System.currentTimeMillis() - startTime;
invalidate();
if (millis > (triggerTime * counter)) {
counter++;
GameView.this.trigger();
}
timerHandler.postDelayed(this, 250);
}
};
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 250);
}
inside the trigger() method:
if (gameIsOver) {
timerHandler.removeCallbacks(timerRunnable);
invalidate();
Intent intent = new Intent(this.context, GameOverActivity.class);
intent.putExtra("EXTRA_SCORE", score);
// some more extras...
((Activity) this.context).startActivity(intent);
((Activity) this.context).finish();
}
EDIT:
GameActivity.java
public class GameActivity extends Activity {
private GameView game;
private int level;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_game);
Intent intent = getIntent();
level = intent.getExtras().getInt("EXTRA_LEVEL");
game = (GameView) findViewById(R.id.game);
game.setLevel(level);
}
}
Related
I have spent almost the day trying to figure it out and yet could not manage to achieve it. I basically have two activities, MainActivity.java and GameActivity.java. The music stops but after going back to MainActivity.java and coming back to GameActivity.java using ImageView several times.
MainActivity.java
public class MainActivity extends AppCompatActivity {
ImageView iv;
public static final String BG_SOUND_CHECK = "background playing!";
// public static MediaPlayer backgroundSound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new Handler();
final MediaPlayer backgroundSound = MediaPlayer.create(this, R.raw.background_music);
handler.postDelayed(new Runnable() {
#Override
public void run() {
backgroundSound.setLooping(true);
backgroundSound.start();
Log.v(BG_SOUND_CHECK, "After loop Started!");
}
}, 3000);
getSupportActionBar().hide();
iv = (ImageView)findViewById(R.id.playImage);
iv.setOnClickListener(new View.OnClickListener(){
public void onClick(View view1){
// backgroundSound.setLooping(false);
backgroundSound.pause();
// Log.v(BG_SOUND_CHECK, "Playing After Play Button Click");
Intent myIntent = new Intent(MainActivity.this, GameActivity.class);
// myIntent.putExtra("backgroundSoundObj",backgroundSound);
startActivity(myIntent);
// Log.v(BG_SOUND_CHECK, "After Game Scene");
}
});
}
}
GameActivity.java
public class GameActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
// MainActivity.backgroundSound.pause();
// Rest of the code
}
}
I tried putting the music onPause(); in
1) ImageView onClick();
2) As soon as the GameActivity.java is loaded
but both ways end up pausing it only after I try coming back to MainActivity.java and going to GameActivity.java several times.
Do you see how you put your backgroundSound.start() inside the postDelayed-3000 ?
backgroundSound.pause() anytime before that 3000ms is not going to do anything.
It has nothing to do with going back and forth between your two activities, it just so happens that doing that takes up more than 3000ms, so when you do click for pause(), 3000ms has passed.
What you can do, to fit your current code, is to separate that into a Runnable.
Runnable bgSound = new Runnable() {
#Override
public void run() {
backgroundSound.setLooping(true);
backgroundSound.start();
Log.v(BG_SOUND_CHECK, "After loop Started!");
}
}
Use it with handler.postDelayed(bgSound, 3000)
In your onClick, if you want to stop it from playing before it starts, can use handler.removeCallbacks(bgSound), to stop it after it plays, your pause(). If you don't care to know if it has or hasn't started, you can do both alongside each other, should work fine too.
(if you don't want the music to play after you've left your main activity, you should also do the same actions in your onDestroy and/or onPause)
As the title suggests I am trying to create a Stopwatch app and am having problems adding a lap button and continue button that work. I have added the buttons to the layout.xml file but am having trouble with the java code that gets them to function.
I need to display the "stopped/paused" time when the lap button is clicked, the internal clock needs to keep running however and no longer be displayed, or the stopped/paused time needs to be shown in a new display whichever is easier to accomplish. When the lap timer is clicked subsequently it should display the current time (internal clock)
I need the continue button to then resume the paused/stopped time.
Could somebody help me with the code, I'm relatively inexperienced in java, so any help would be appreciated
here's the code of my main java file:
package com.hfad.stopwatch;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.TextView;
public class StopwatchActivity extends Activity implements View.OnClickListener {
Button Continue;
Button lapChrono;
Chronometer chrono;
long time =0;
//Number of seconds displayed on the stopwatch.
private int seconds = 0;
//Is the stopwatch running?
private boolean running;
private boolean wasRunning;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stopwatch);
Continue=(Button)findViewById(R.id.Continue_button);
lapChrono=(Button)findViewById(R.id.lap_button);
lapChrono.setOnClickListener(this);
Continue.setOnClickListener(this);
chrono=(Chronometer)findViewById(R.id.chronometer);
if (savedInstanceState != null) {
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
runTimer();
}
#Override
protected void onPause() {
super.onPause();
wasRunning = running;
running = false;
}
#Override
protected void onResume() {
super.onResume();
if (wasRunning) {
running = true;
}
}
public void onClick(View arg0) {
switch (arg0.getId()){
case R.id.Continue_button:
chrono.setBase(SystemClock.elapsedRealtime()+time);
chrono.setBase(time);
break;
case R.id.lap_button:
time = chrono.getBase()+SystemClock.elapsedRealtime();
break;
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("seconds", seconds);
savedInstanceState.putBoolean("running", running);
savedInstanceState.putBoolean("wasRunning", wasRunning);
}
//Start the stopwatch running when the Start button is clicked.
public void onClickStart(View view) {
running = true;
}
//Stop the stopwatch running when the Stop button is clicked.
public void onClickStop(View view) {
running = false;
}
//Reset the stopwatch when the Reset button is clicked.
public void onClickReset(View view) {
running = false;
seconds = 0;
}
//Sets the number of seconds on the timer.
private void runTimer() {
final TextView timeView = (TextView)findViewById(R.id.time_view);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds/3600;
int minutes = (seconds%3600)/60;
int secs = seconds%60;
String time = String.format("%d:%02d:%02d",
hours, minutes, secs);
timeView.setText(time);
if (running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
I am just having problems getting things to run smoothly as I'm not too fluent in my Java, apologies, that is why help is needed. The logic isn't quite there. The continue button doesn't function properly nor does the lap, I'm needing it to function as described above.
chrono object is not initialized and used in onClick(). Hence NPE occurs.
Try to initialise it in onCreate().
Im trying to build easy app that the user need to remmber on which buttons the computer pressed ..
Each button that clicked make a sound .. so in order to make each sound ,sound correctly I tried to give a little bit of delay between each click that the computer pressed...
So I make int[] that include the sequence of the way the computer click the buttons ( for 1 click on button1 , for 2 click on button 2 .... )
and now im trying to acually pressed the button haha
so I made this :
private void ClickButtons(int[] sequence) {
Button btcomp1 = (Button) findViewById(R.id.btComp1);
Button btcomp2 = (Button) findViewById(R.id.btComp2);
Button btcomp3 = (Button) findViewById(R.id.btComp3);
Button btcomp4 = (Button) findViewById(R.id.btComp4);
TextView check=(TextView)findViewById(R.id.textViewKq);
Handler handler = new Handler();
for (int i = 0; i < sequence.length; i++)
{
switch (sequence[i]) {
case 1:
btcomp1.performClick();
check.setText("4..");
timedelay();
break;
case 2:
btcomp2.performClick();
check.setText("3..");
timedelay();
break;
case 3:
btcomp3.performClick();
check.setText("2..");
timedelay();
break;
case 4:
btcomp4.performClick();
check.setText("1..");
timedelay();
break;
}
}
}
it didnt work well , I even thought that their is may be problem with the button so I set it for changing some Textview but its seems that its only enter to one case ... and the only delay was when I mover from the FirstActivity to the GameActivity
I really have nothing in the FirstActivity just field for UserName ...
Well I hopes you helped me guys and soory for grammer ><
This is the delay .. I tried to do something but all that do is to delay me a few seconds after I gor from actity 1 to another but do nothing in the main ..
private void timedelay() {
try{
Thread.sleep(2500);
}
catch (Exception e){
}
}
For this kind of thing you should definitely use the android.os.Handler to make a timer. And in the callback method, click the buttons. The method you are using now will probably block the main thread. This is really bad.
Luckily, I have already written a Timer class does this! Here is the whole class:
import android.os.Handler;
public class Timer {
private Handler handler;
private boolean paused;
private int interval;
private Runnable task = new Runnable () {
#Override
public void run() {
if (!paused) {
runnable.run ();
Timer.this.handler.postDelayed (this, interval);
}
}
};
private Runnable runnable;
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void startTimer () {
paused = false;
handler.postDelayed (task, interval);
}
public void stopTimer () {
paused = true;
}
public Timer (Runnable runnable, int interval, boolean started) {
handler = new Handler ();
this.runnable = runnable;
this.interval = interval;
if (started)
startTimer ();
}
}
Try to understand it. After you do that, you can use this timer like this:
final Timer t = new Timer(new Runnable() {
private int i = 1;
Button btcomp1 = (Button) MainActivity.this.findViewById(R.id.btComp1);
Button btcomp2 = (Button) MainActivity.this.findViewById(R.id.btComp2);
Button btcomp3 = (Button) MainActivity.this.findViewById(R.id.btComp3);
Button btcomp4 = (Button) MainActivity.this.findViewById(R.id.btComp4);
TextView check=(TextView)MainActivity.this.findViewById(R.id.textViewKq);
public void run() {
switch (i) {
case 1:
btcomp1.performClick();
check.setText("4..");
break;
case 2:
btcomp2.performClick();
check.setText("3..");
break;
case 3:
btcomp3.performClick();
check.setText("2..");
break;
case 4:
btcomp4.performClick();
check.setText("1..");
t.stopTimer();
break;
}
}
}, 1000, true);
Once this timer is created, it basically presses a button once a second. And set the text of check. When it presses it the fourth time, the timer stops.
Easy! (if you have the timer class)
I want to make a temporary Activity that allowed me to show it , For Example it is appear only for 5 seconds so how can I make it >> Like a hello screen in the beginning in my app .
By the way I am using Android Studio
The splash screen displays for 2 seconds and then the main activity of the application appears. For this, we add a java class that displays the splash screen. It uses a thread towait for 2 seconds and then it uses an intent to start the next activity.
public class SplashScreen extends Activity {
private long ms=0;
private long splashTime=2000;
private boolean splashActive = true;
private boolean paused=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread mythread = new Thread() {
public void run() {
try {
while (splashActive && ms < splashTime) {
if(!paused)
ms=ms+100;
sleep(100);
}
} catch(Exception e) {}
finally {
Intent intent = new Intent(SplashScreen.this, Splash.class);
startActivity(intent);
}
}
};
mythread.start();
}
}
Before I start I have looked at lots of threads including:
How to add time to countdown timer?
Android game countdown timer
But I just cant get my timer to work in the way I require. I want the timer to be counting down from say 30 and when and image is pressed (named imageview1 in this case) the timer adds 3 seconds to the timer to give it more time. I know you cannot essentially add the time while its running and you need to cancel and then start a new timer, The code I have so far is :
public void onClick(View v) {
// TODO Auto-generated method stub
//GlobalClass global = new GlobalClass();
Random rand = new Random();
CountDownTimer thetimer = new myTimer(millisInFuture, 1000);
switch(v.getId()) {
case R.id.buttonstart:
btnstart.setVisibility(View.INVISIBLE);
thetimer.start();
break;
case R.id.imageView1:
if (thetimer != null){
thetimer.cancel();
thetimer = new myTimer(countdownPeriod + 3000, 1000).start();
}
break;
with lots of other case references then :
public class myTimer extends CountDownTimer {
public myTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
timedisplay.setText("Time Left: " + millisUntilFinished / 1000);
countdownPeriod=millisUntilFinished;
}
#Override
public void onFinish() {
timedisplay.setText("Timer Finished");
started = false;
btnstart.setVisibility(View.VISIBLE);
}
}
I think the problem is its not cancelling the original timer so the label that shows the timer does some crazy things, like jumping around on different numbers both up and down as there would appear more than 1 class of thetimer. That is even though I have included the line thetimer.cancel(); The timer works fine if I just let it run to 0.
Any help would be great
You should not create your timer as a local in onClick. Instead create it as a global and start it somewhere else (in onCreate perhaps).
What happens with your current code is that whenever onClick is called a new timer is created and you then cancel the new timer - which has no effect on any previously created timer(s).
Try something like this:
public class MyActivity extends Activity {
CountDownTimer thetimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
thetimer = new myTimer(millisInFuture, 1000);
}
public void onClick(View v) {
Random rand = new Random();
switch(v.getId()) {
case R.id.buttonstart:
btnstart.setVisibility(View.INVISIBLE);
thetimer.start();
break;
case R.id.imageView1:
if (thetimer != null) {
thetimer.cancel();
thetimer = new myTimer(countdownPeriod + 3000, 1000).start();
}
break;
}
}
}
You will still have to keep track of the global time somewhere - i.e. the countDonwPeriod used to re-create the timer instance when an image is touched - it should probably be extracted from the timer before canceling it.