I'm working on a Minecraft Bukkit plugin, I know how to handle events and everything, but I'm not sure how to do this. I haven't actually written the code yet so here's a basic example of what I want to do:
public void playerDead() {
runCommand(commandHere)
//Wait 2 minutes.
runCommand(otherCommandHere
}
I just need the part to wait two minutes. Everything else is covered.
EDIT2: Seems I need to reset the delay to the beginning if someone else dies while it's going. Any suggestions?
Since I see you want to perform your action after the player has died. Then for sure you don't want to halt the main Thread with Thread.sleep(x);
What you can do is create a cooldown for the player that passed away.
public Map<String, Long> cooldown = new HashMap<String, Long>();
Long time = cooldown.get(player.getName());
if(time - System.currentTimeMillis() > 10*1000)
cooldown.put(player.getName(), System.currentTimeMillis());
else
int remains = (int)Math.floor(10 - System.currentTimeMillis());
Code reference here.
Or you can create your task to run like this:
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
{
public void playerDied()
{
// Your code here.
}
}, <delay in ticks>);
Get a reference to your plugin and pass it as the parameter plugin. Or if you are lazy just write it inside the plugin and pass it this.
You should use the BukkitScheduler provided by Bukkit.
You have to save the BukkitTask object returned by the Scheduler.runTaskLater(...) method to use it later.
Every time playerDead() is called, you can reset the delay by cancelling and restarting the task.
BukkitTask task;
public void playerDead() {
// Command here
if (task != null) {
task.cancel();
}
task = getServer().getScheduler().runTaskLater(Plugin, new Task(), 2400L);
}
public class Task extends BukkitRunnable {
#Override
public void run() {
// Other command here
task = null;
}
}
You may try like this:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
runCommand(commandHere);
}
}, 120000);
Related
I need to call the speak method every 5 minutes, then i want to run in background the async method called callspeak, that calls back the speak method(a public method of a different class). It has to loop every 5 minutes
class callSpeak extends AsyncTask<String, Void, String> {
activityAudio a = new activityAudio();
#Override
protected String doInBackground(String... strings) {
try
{
while (true){
a.speak();
Thread.sleep(300000);
}
}
catch (InterruptedException e)
{e.getMessage();}
return null;
}
}
If you want to run the method only when the app is open, you can simply use TimerTask.
Timer myTimer = new Timer ();
TimerTask myTask = new TimerTask () {
#Override
public void run () {
// your code
callSpeak().execute() // Your method
}
};
myTimer.scheduleAtFixedRate(myTask , 0l, 5 * (60*1000)); // Runs every 5 mins
If you want to run it in background even if app is not running, you can use AlarmManager and repeat the task every 5 mins.
Hope it helps
You can do like this:
Handler mHandler = new Handler();
Runnable mRunnableTask = new Runnable()
{
#Override
public void run() {
doSomething();
// this will repeat this task again at specified time interval
mHandler.postDelayed(this, yourDesiredInterval);
}
};
// Call this to start the task first time
mHandler.postDelayed(mRunnableTask, yourDesiredInterval);
Don't forget to remove the callbacks from handler when you no longer need it.
The latest and the most efficient way to perform this, even if you come out of the activitiy or close the app is to implement the WorkManager from the AndroidX Architecture.
You can find more details here from the official documentation: Schedule tasks with WorkManager
Hello Developers This question may seem foolish to some readers and it may have answered before but I have seen many answers on this forum regarding my issue but I could not understand single one of them. So please be kind and answer my question if you could.
The thing is I am trying to develop something like a game and trying to add computer or AI player against a human player.
For that I added a CountdownTimer in OnCreate method and it worked fine only once as OnCreate executes only once. But when I tried to add a while loop inside a runnable and inside that while loop I added the same CountdownTimer but it started giving me errors.
if(player2_name.equals("Computer")) {
Runnable r = new Runnable() {
#Override
public void run() {
while (player2_name.equals("Computer")) {
CountDownTimer computer_player;
ct = 5;
firstplayer_game_button.setClickable(false);
computer_player = new CountDownTimer(5000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
ct = ct - 1;
// timer_counter.setText("" + ct);
if (ct == 1) {
firstplayer_game_button.setClickable(true);
}
}
#Override
public void onFinish() {
// secondplayer_game_button.setBackgroundResource(R.drawable.button_player_2);
// firstplayer_game_button.setBackgroundResource(R.drawable.button_player_1);
// firstplayer_game_button.setClickable(true);
if (player2_name.equals("Computer")) {
secondplayer_game_button.setClickable(false);
} else {
secondplayer_game_button.setClickable(true);
}
if (checker != 1) {
Click_Condition_checker(2);
}
}
};
computer_player.start();
}
}
};
Thread mythread = new Thread(r);
mythread.start();
I know that a Runnable cannot interact with UI directly and for that we need handlers that is why I commented all the UI interfaces. But still no luck. And unfortunately I am not able to identify the errors. If Someone can help then it would be very kind for a foolish developer like me.
First, you don't need to use Runnable to make a CountDownTimer works. It's because CountDownTimer can directly interact with the UI if the code running inside the Activity.
Second, you should not use while loop inside your code. Especially for the following code:
while (player2_name.equals("Computer")) {
CountDownTimer computer_player;
...
computer_player = new CountDownTimer(5000, 1000) {}
...
}
which means you're creating new object until you exhausted all the device memory or until player2_name is not "Computer".
You should using a boolean flag instead.
I think what you need is can be achieved by restarting the CountDownTimer with something like this:
// use a more readable variable name instead of computer_player
final CountDownTimer cdtPlayer = new CountDownTimer(5000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
// do something
}
#Override
public void onFinish() {
// do something
// restart to do all again
cdtPlayer.start();
}
};
cdtPlayer.start();
Regarding your following statement:
If Someone can help then it would be very kind for a foolish developer like me.
Everybody is a foolish when starting to learn something. Don't be too hard with yourself ;)
Not sure about your goal but your while loop seems troublesome. A while testing a string and not changing its value, it's going to run over and over (and by then create that many CountdownTimer which I don't think was your intent)
When I start the app "specific function" needs to be executed.
After 10 seconds "specific function" needs to be triggered again.
After this second operation "specific function" should not triggered again.
There are two way to handle your problem.
If there is any condition you want to check and accordingly do the work after every 10 seconds You should Use a Handler.
If there is no condition on anything and you just want to run the code after every 10 Seconds. Then TimerTask is also one way. I have actually worked with TimerTask class. So i say it is quite easy.
Creating your class and implementing the methods.
class myTaskTimer extends TimerTask{
#Override
public void run() {
Log.e("TAG", "run: "+"timer x");
}
}
and now in your code Create a new Timer Object and initialize it.
Timer t = new Timer();
Now you can schedule your task in it after a specified interval like below:
t.scheduleAtFixedRate(new myTaskTimer(),10000,10000);
The function is explained below:
void scheduleAtFixedRate (TimerTask task,
long delay,
long period)
Schedules the specified task for repeated fixed-rate execution,
beginning after the specified delay. Subsequent executions take place
at approximately regular intervals, separated by the specified period.
and now for handler , below is the code and it can check for any condition. Code taken from here for your help.
private int mInterval = 10000; // 10 seconds as you need
private Handler mHandler;
#Override
protected void onCreate(Bundle bundle) {
// your code here
mHandler = new Handler();
startRepeatingTask();
}
#Override
public void onDestroy() {
super.onDestroy();
stopRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try {
updateStatus(); //this function can change value of mInterval.
} finally {
// 100% guarantee that this always happens, even if
// your update method throws an exception
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
I hope it helps.
Use android.os.Handler as per #pskink comment.
private void callSomeMethodTwice(){
context.myMethod(); //calling 1st time
new Handler().postDelayed(new Runnable(){
#Override
public void run(){
context.myMethod(); //calling 2nd time after 10 sec
}
},10000};
}
This is probably a very easy question but, How do I use a timer to run code again and again until a boolean value e.g. Testing is equal to true?
Obviously I would use a while loop but I don't want it to stop the rest of the work taking place on the main ui thread
If your process is running simultaneously, use a Handler and use its postDelayed(Runnable, long) to post a callback implementing the Runnable interface.
A rather naive example:
final handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
if (<EXPRESSION>) {
// Evaluated true, do your stuff and exit the polling loop.
} else {
handler.postDelayed(this, <TIMEOUT>);
}
}
handler.postDelayed(r, <TIMEOUT>);
You can use AlarmManager class to manage your thread. its simple to use.
for more info you can visit Android SDK Doc
timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
if(flagIsOn)
{
timer.cancel();
timer.purge();
}
}
}, 0, 1000);
This could be a duplicate question but I did not find what I was looking for.
I am calling an AsyncTask in the UI activity new LoadData().execute(); and in doInBackground I call a method which takes time. I want to interrupt this thread if the data is not return after some time.
Below is the code how I tried to do this.
class LoadData extends AsyncTask<String, String, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
startTime = System.currentTimeMillis();
}
protected String doInBackground(String... args)
{
DataCollector dc = new DataCollector();
data = dc.collectData(query);
//Here I check if the time is greater than 30 seconds then cancel
if(((System.currentTimeMillis()-startTime)/1000)>30)
{
cancel(true);
}
return null;
}
}
But this does not stop the task after 30 seconds, in fact it is taking more time.
I have tried get(long timeout, TimeUnit unit); as well but that does not work either.
Can anyone show me how can I do it or how do I use isCancelled() in doInBackground.
Thanks.
You need a thread that cancels your task after a certain amount of time. That Thread could look like this:
public class TaskCanceler implements Runnable{
private AsyncTask task;
public TaskCanceler(AsyncTask task) {
this.task = task;
}
#Override
public void run() {
if (task.getStatus() == AsyncTask.Status.RUNNING )
task.cancel(true);
}
}
And when you call your AsyncTask, you need to run the cancle task after a certain amount of time (=the timeout, in this case 20 sec)
private Handler handler = new Handler();
private TaskCanceler taskCanceler;
...
LoadData task = new LoadData();
taskCanceler = new TaskCanceler(task);
handler.postDelayed(taskCanceler, 20*1000);
task.execute(...)
It's a good idea if you clean this up on cancel or finish with
if(taskCanceler != null && handler != null) {
handler.removeCallbacks(taskCanceler);
}
You can of course wrap this in an custom implementation of AsyncTask. I've used this pattern many times and it works like a charm. One thing to note, in rare cases the handler would not start, I suspect if you create it in the wrong context it will not survive in certain instances, so I forced the handler to be an the UI Thread with handler= new Handler(Looper.getMainLooper());
You have to do the Time check on a different thread.
What you currently do is: executing the dc.collectData(query) (in background) and once it is ready you check if you should cancel. So if the query takes 1 minute, you will do the cancel check after 1 minute, which is already too late.
What you could do is schedule a TimerTask that should run 30 seconds after the LoadData().execute() and if the timer Task is run, you can cancel the AsyncTask (if it is still running)
I would translate this into an async/await problem making all the expensive methods as async methods.
First, Modify DataCollector's collectData(query) to collectDataAsync(query). (If you can't modify DataCollector, there are work arounds to wrap it in a lambda function or something similar).
Second, change doInBackground as an async task, something like this:
protected async Task<String> doInBackgroundAsync(String... args)
{
DataCollector dc = new DataCollector();
int timeout = 1000;
var task = dc.collectDataAsync(query);
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// task completed within timeout
data = task.Result;
} else {
// timeout logic
}
}
Basically, you have two tasks inside doInBackgroundAsync: collectDataAsync and a delay task.
Your code waits for the faster one. Then you know which one was and you can react accordingly.
If you also need to cancel collectDataAsync task, then you want to used a cancellationToken.
I use this to solve your problem https://stackoverflow.com/a/11191070/3307066.
Note that now doInBackgroundAsync is a async, so it changes a bit the way of using it.
Hope it helps.
Short answer is you CAN'T cancel an AsyncTask once its started. What you can do, is insert a loop inside doInBackGround() which will check for isCancelled() and if it is set to true sometime in the future - return a value from the function (which will in turn call onPostExecute() if you have defined it);
Note that just because you can't stop an AsyncTask doesn't mean that the OS won't cancel it if it's low on memory. You should have this in mind if you are doing essential tasks in the AsyncTask (ones that you want executed 100%). If so, it is better to use a Service - a component that is automatically killed and restarted by the OS as need.
try this :
public class MyTask extends AsyncTask<Void, Void, Void> {
private volatile boolean running = true;
private final ProgressDialog progressDialog;
public MyTask(Context ctx) {
progressDialog = gimmeOne(ctx);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
// actually could set running = false; right here, but I'll
// stick to contract.
cancel(true);
}
});
}
#Override
protected void onPreExecute() {
progressDialog.show();
}
#Override
protected void onCancelled() {
running = false;
}
#Override
protected Void doInBackground(Void... params) {
while (running) {
// does the hard work
}
return null;
}
// ...
}
Courtesy and for more details see this answer.