Simultaneous, linked threads in android - android

I'm working on a math game which presents the player with a simple math problem of the sort 4 + 3 = ? or 6 / 2 = ?. The player is offered 4 possible answers and clicks one. The screen has two buttons, one with an arrow, and one with a square.
The player selects the answer they think is correct. If the answer is correct they get a message. If the answer is incorrect, that choice is grayed out, and they can keep choosing until they get it right.
I want two modes of play: practice and timed.
In practice mode, the player clicks the arrow button and gets a new question. This works fine.
I also want a timed play mode. When the player presses the arrow button, a timer starts and the first problem comes up. If they get it right, they are immediately asked a new question. Again, if they are incorrect, they keep asking until they get it right. Meanwhile, there should be a timer counting down. Play stops when the timer ends or the player presses the square button.
I don't know how to do the timed play where there are two simultaneous activities: playing the game, and the timer.
I'm including pseudo-code instead of code -- the code is long. But if necessary, I can post the entire code.
Update:
This was my naive attempt. The problem is that I can't figure out how to wait in the while loop for until the player to ask the question before askQuestion() is called again. Perhaps it needs to be in a separate thread and have the while loop wait for that thread to return. Would the timer keep going? I want the timer to run simultaneously to a separate task in which a question is posed --> Player answers the question --> a new question is posed .....
public void playTimed()
{
// Toast.makeText(getApplicationContext(), "in playPractice", Toast.LENGTH_SHORT).show();
go_button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
go_button.setEnabled(false);
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished)
{
timer.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish()
{
timer.setText("done!");
go_button.setEnabled(true);
timer_done = true;
}
}.start();
while(!timer_done)
{
askQuestion();
}
}
});
}
onCreate()
{
-For all four answer buttons:
answer_button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
correct = checkAnswer(answer_button_id);
}
});
-get intent extras to know which game
-swith-case to play selected game
}
checkAnswer()
{
if (correct)
{
// feedback
handleRightAnswer();
}
else
{
// feedback
handleWrongAnswer();
}
}
askQuestion()
{
-choose type of problem (+,-,*,/)
-generate arguments and answer
-create random answer list
where one choice is correct
-display problem
-display answer choices
}
playTimed()
{
-When player presses go_button,
timer starts and first question
appears. When correct answer is
selected a new question immediately
appears. Continues until timer runs
out or player presses stop_button.
Seconds left is displayed during play.
}
playPractice()
{
//When player presses go_button
// a new question appears.
go_button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
askQuestion();
}
});
}

As Gabe Sechan stated, you can do this using a timer to update a counter, then when the counter hits 0, do something. You can also use the timer to update a TextView (to display the time remaining).
Here is a class that I have used in the past, originally found here:
public class UIUpdater{
private Handler mHandler = new Handler(Looper.getMainLooper());
private Runnable mStatusChecker;
private int UPDATE_INTERVAL = 1000; //updates every second
public UIUpdater(final Runnable uiUpdater) {
mStatusChecker = new Runnable() {
#Override
public void run() {
// Run the passed runnable
uiUpdater.run();
// Re-run it after the update interval
mHandler.postDelayed(this, UPDATE_INTERVAL);
}
};
}
public UIUpdater(Runnable uiUpdater, int interval){
this(uiUpdater);
UPDATE_INTERVAL = interval;
}
public synchronized void startUpdates(){
mStatusChecker.run();
}
public synchronized void stopUpdates(){
mHandler.removeCallbacks(mStatusChecker);
}
}
Then, in your method where you want to update your counter, you would put:
UIUpdater mUIUpdater = new UIUpdater(new Runnable() {
#Override
public void run() {
//method to update counter
}
});
//to start the method:
mUIUpdater.startUpdates();
//to stop the method, ie, when counter == 0
mUIUpdater.stopUpdates();

Related

How to obtain the expected order of actions in my game loop?

I don't fully understand what is going on behind the scene, and therefore, what I can do to correctly code this issue. I'm looking for an explanation that will lead me to figure it out myself. This is just a fun home based project(I'm not a student), where I'm coding a turn based app. However, the battle scenes are randomly calculated durations, rather than turn based, so my desire is as follows:
Present initial battle count on screen for 2 seconds
Calculate first skirmish
Present updated battle count on screen for 2 seconds
Calculate 2nd skirmish
...
...
Present Victory or Defeat on screen
The problem I'm having is that the app is performing as follows currently:
Present initial battle count on screen
Calculate all skirmishes
Page displays null for the number, since it's apparently already returned?
Code looks like this:
void fightBattle(){
setContentView(R.layout.brigands);
boolean winnerDetermined = false;
while(!winnerDetermined) {
boolean brigandsWon = brigandsWon(player, brigandCount);
if(brigandsWon) {
player.removeWarriors(2);
}
displayWarriors(player);
if(brigandsWon){
if(player.getWarriors() < 2){
winnerDetermined = true;
}
}
if(!brigandsWon) {
brigandCount = brigandCount / 2;
}
displayBrigands();
if(brigandCount == 0){
winnerDetermined = true;
}
}
}
private void displayWarriors(Player player){
final Player currentPlayer = player;
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
setContentView(R.layout.warriors);
TextView warrior_count_tv = findViewById(R.id.warrior_count_tv);
warrior_count_tv.setText(currentPlayer.getWarriors());
}
}.start();
}
private void displayBrigands(Player player){
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
setContentView(R.layout.brigands);
TextView brigand_count_tv = findViewById(R.id.brigand_count_tv);
brigand_count_tv.setText(Integer.toString(brigandCount));
}
}.start();
}
Ultimately, what I want to see is something like the below sudo-code:
displayPage1For2Seconds;
while(somethingIsTrue){
calculateNumber;
displayPage2For2Seconds;
displayPage3for2Seconds;
}
displayPage4For2Seconds;
Calculate all skirmishes
Your current code does this because the while loop doesn't actually stops to wait. The flow will be like this:
enter while loop -> call displayWarriors() -> create CountDownTimer() to do something after 2 seconds -> return to while loop -> call displayBrigands() -> create CountDownTimer() to do something after 2 seconds -> return to while loop -> do the same until you exit while
With this code you'll end up with a bunch of CountDownTimers that are created and executed at the same(almost) time so after two seconds they all try to set a view to some value(with an indefinite behavior like you mention it happens).
There are several ways to do what you want. You could use a Thread for example:
void fightBattle(){
setContentView(R.layout.brigands);
new Thread(new Runnable() {
public void run() {
// I assume R.layout.brigands is the initial screen that you want to show for 2 seconds?!? In this case wait 2 seconds
TimeUnit.Seconds.sleep(2);
boolean winnerDetermined = false;
while(!winnerDetermined) {
// ...
// from your code it seems you want to show this for 2 seconds?
displayWarriors(player);
TimeUnit.Seconds.sleep(2);
//...
displayBrigands();
// also show this for 2 seconds
TimeUnit.Seconds.sleep(2);
// ...
}
}
}).start();
}
Then your display methods will be something like this:
private void displayWarriors(Player player){
// you need to wrap this code in a runOnUiThread() method(from the activity)
// because we are on a background thread and we are changing views!
final Player currentPlayer = player;
setContentView(R.layout.warriors);
TextView warrior_count_tv = findViewById(R.id.warrior_count_tv);
warrior_count_tv.setText(currentPlayer.getWarriors());
}
Another approach would be to use a Handler and break your code in Runnables that you then schedule at appropriate times.

Auto Redirect When User Is Taking Too Long Input In Activity Android

I have a scenario, which when a User Rating, or inputting on a data, then the current Activity will Time it to the setted time.
So, if the User isn't do Anything, or taking the Action to Long, then the current Activity will direct the User into the MainActivity.
In my case, i have a Rating app, which is located in a Public place. I thought that if People wants to Rate BUT not completing the Quiz phase, then i don't want to leave the last Quiz to meet the new People who wants to Rate.
I've tried using these code:
int timeout = 4000;
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Intent homepage = new Intent(Quiz2.this, MainActivity.class);
startActivity(homepage);
finish();
}
}, timeout);
And these one:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(Quiz2.this, MainActivity.class));
}
}, 4000);
It works, but it didn't work as expected, as it apply to ALL of the activities (I mean, after these code works in Current Activity, the Rest of the Activities is Applied and Timed too)
I don't want this. What i want is to Apply these Timer ONLY in Current Activity.
How this can be done?
Appreciate for any help, Regards.
I didn't fully understand what you actually wanna do,
but I'm guessing using CountDownTimer and then starting the other activity when the timer finished should do the trick.
new CountDownTimer(4000, 1000) {
public void onTick(long millisUntilFinished) {
// You could show the user the time left using `millisUntilFinished`
}
public void onFinish() {
// Do something when the timer is finished (start your activity & finish)
}
}.start();

use a Runnable multiple times in android and it's effect on memory

I defined a Runnable which starts after a button clicked,
it changes image of a ImageView every 1 second.
There is an other button in my view that when user click on that, again I start that Runnable but this time it changes image of ImageView every 2 seconds and so on.
My question is: when I click on second button, now do I have to individual thread running or it just stop first instance of Runnable and start the other instance?
Note: I read some topics about threads and Runnable in android but still the different is not clear for me.
Also reading this question and it's answers head me hear to ask my own question.
Java - Running a thread twice
Sorry for bad English.
Runnable part of my code:
private final Runnable mRunnable = new Runnable() {
public void run() {
if (mIsFlashOn) {
if (mSwap) {
mImageViewBeam.setVisibility(View.VISIBLE);
mSwap = false;
mHander.postDelayed(mRunnable, 10000 / ((mStrobeCounter * 5) + 10));
} else {
mImageViewBeam.setVisibility(View.GONE);
mSwap = true;
mHander.postDelayed(mRunnable, 10000 / ((mStrobeCounter * 5) + 10));
}
}
}
};
I think you need to use mHandler.removeCallbacks(mRunnable); this line to remove first runnable , and than start another
So from your code what have I understood is, you're creating a thread inside a while loop which is updating the ImageView over the time. If I've understood correctly then its really a bad practice to do so. I might be wrong. Please post your updating code in that case. How you're updating the ImageView?
If I'm right, try considering CountDownTimer which will serve your purpose I hope.
CountDownTimer mCountDownTimer = new CountDownTimer(howLongYouWantItToRunInMilis, intervalInMilis) {
public void onTick(long remainingMilis) {
// Update your ImageView here
if (mSwap) {
mImageViewBeam.setVisibility(View.VISIBLE);
mSwap = false;
} else {
mImageViewBeam.setVisibility(View.GONE);
mSwap = true;
}
}
public void onFinish() {
// Start the timer again from the code.
}
}.start();
Set the intervalInMilis when the button is clicked. Then mCountDownTimer.cancel() to cancel the timer and mCountDownTimer.start() to start it again immediately.

How can I control a timer in android?

I want to make an application about mini game.
Detail : In 2 seconds you must to answer a question if you don't answer or the answer is wrong -> Game Over . But if your answer is true the Timer will reset become 0 and countdown again with diffirent question.
I have already seen many code about timer in website but I don't understand clearly about it :(
So I want to ask : How can i set up a timer run only 2 seconds and how can i reset it and continue with a new question ?
Please help me.
you can use CountDownTimer in android like this:
public class Myclass {
myTimer timer =new myTimer(2000,1000);
public void creatQuestion(){
timer.start();
//method you init question and show it to user
}
public void getUserAnswer(/*evry thing you expected*/)
{
//if answer is true call timer.start()
//else call timer.onFinish(); to run onfinish in timer
}
public class myTimer extends CountDownTimer {
public myTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
// you can update ui here
}
#Override
public void onFinish() {
this.cancel();
//fire game over event
}
}
}
i hope it make you satisfy
I've done something similar using Thread/Runnable.
Thread t = new Thread(new Runnable() {
public void run() {
final long startTime = getTime();
final long maxEndTime = startTime + 2000L;
try {
while (shouldContinueWaiting()) {
if (getTime() > maxEndTime) {
throw new TimeoutException();
}
sleep();
}
} catch (InterruptedException e) {
handleInterrupt();
} catch (TimeoutException e) {
handleTimeout();
}
}
boolean shouldContinueWaiting() {
// Has the user already answered?
}
void handleInterrupt() {
// The user has answered. Dispose of this thread.
}
void handleTimeout() {
// User didn't answer in time
}
void sleep() throws InterruptedException {
Thread.sleep(SLEEP_DURATION_IN_MILLIS);
}
void getTime() {
return System.currentTimeMillis();
}
then you can start/restart the thread by:
t = new Thread(same as above...);
t.start();
and stop by:
t.interrupt();
We want to use the Timer class.
private Timer timer;
When you're ready for the timer to start counting -- let's say it's after you press a certain button -- do this to start it:
timer = new Timer();
timer.scheduleAtFixedRate(incrementTime(), 0, 100);
The first line is us creating a new Timer. Pretty standard. The second line, however, is the one I wanted you to see.
incrementTime() is a method that is called at the end of every "tick" of the clock. This method can be called whatever you want, but it has to return an instance of TimerTask. You could even make an anonymous interface if you want, but I prefer moving it off into its own section of code.
The 0 is our starting location. We start counting from here. Simple.
The 100 is how large a "tick" of the clock is (in milliseconds). Here, it's every 100 milliseconds, or every 1/10 of a second. I used this value at the time of writing this code because I was making a stopwatch application and I wanted my clock to change every 0.1 seconds.
As for your project, I'd suggest making the timer's task be your question switch method. Make it happen every 2000 milliseconds, or 2 seconds.
You can use a Handler.
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//this will happen after 2000 ms
}
}, 2000);
Maybe this can help you:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
// FIRE GAME OVER
handler.postDelayed(this, 2000); // set time here to refresh textView
}
});
You can fire your game over after 2000 milliseconds.
If you get the question correct -> remove callback from handler and reset it when the next question starts.

My android app shows a video and must be always running, but after few hours my app is stopped

I'm new on android application and i'm creating an app that shows a video using a VideoView, I use a CountDownTimer to search each 15 seconds for video updates and play another video. My app works very well during 2 or 3 hours but after this my app just stop, the application doesn't close but is stopped and I must close and open again. What should I do? Thanks.
It literally stops on the screen, it stops the timer and video view.
Here is the code that i'm using to count time to call functions to show video and time.
new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
time++;
downloadTime++;
if(downloadTime == 2){ // Should be executed each 2 seconds
DoDownloads();
downloadTime = 0; //
}
showPlayer();
showTime();
}
public void onFinish() {
this.start();
}
}.start();
I can't show any log because this happens after some hours and can be 2 hours or 10 hours, and i'm testing on tablet.
We would need the code of the rest of your functions, like DoDownloads(); showPlayer(); showTime();
anyways, i wouldnt restart the countdown that way. Id try with a handler and postdelayed(Runnable), like:
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
time++;
downloadTime++;
if(downloadTime == 2){ // Should be executed each 2 seconds
DoDownloads();
downloadTime = 0; //
}
showPlayer();
showTime();
handler.postDelayed(this, tiempo);
}
};
handler.postDelayed(runnable, tiempo);
And also, you should debug the app and copy/past the log cast in the moment it fails, and give us some information about in what point the execution wsa

Categories

Resources