Unable to reschedule timer in Android - android

i am working on a simple app. in my app i am using timerTask like this:
TimerTask saveData=new TimerTask() {
#Override
public void run() {
saveDatatoFile();
}
};
i call TimerTask in onCreate() of my activity like:
int file_saving_pollingtime=60000;
timer.schedule(saveData,10000,file_saving_pollingtime);
its working fine. i wants to change the file_saving_pollingtime on realtime basis for it i am using BroadcastReceiver to read message of specific pattern which contains the file_saving_pollingtime. i successfully read the file_saving_pollingtime from message and store it in sheared preference. but i am unable to refresh the file_saving_pollingtime of timer as per message file_saving_pollingtime:
if (frequency.matches(regexStr)){
editor.putString(FILE_FREQUENCY, frequency);
editor.commit();
int fre=Integer.parseInt(sharedPreferences.getString(FILE_FREQUENCY, "0"));
int freq=fre*1000;
Log.d("dfdfdfdf", String.valueOf(freq));
Novipod mv=new Novipod(); //mv is the instance of main activity class
mv.timer.cancel();
mv.timer.schedule(mv.saveData,1000,freq);
}
please help me guys

Try with following code:
public void rescheduleTimer() { // call it to reschedule the timer
if(timer != null){
timer.cancel();
}
timer = new Timer();
timerTask = new MyTimerTask();
timer.schedule(timerTask,1000,freq);
}
private class MyTimerTask extends TimerTask {
#Override
public void run() {
saveDatatoFile();
}
}

Related

Timer object doubles when I change activity and come back

So I'm trying to make a clicker game that is about money. Every time you click the middle button it gives you 1€, but it also gives 1€/second.
I'm having a problem when I go to the shop activity and then come back to MainActivity, it counts as 2 timers are running, and if I alternate activities again, it counts as if 3 Timers were running at the same time. Thats giving me issues because I declared "money_per_sec" int, and dont want 2€/s or more just because I click on "Shop".
Any help?
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
money = loadGame.getInt("money", 0);
money_per_sec = loadGame.getInt("money_per_sec", 0);
money_per_click = loadGame.getInt("money_per_click", 0);
money = money + money_per_sec;
SharedPreferences saveGame = getSharedPreferences(SAVE, 0);
SharedPreferences.Editor editor = saveGame.edit();
editor.putInt("money", money);
editor.putInt("money_per_sec", money_per_sec);
editor.apply();
runOnUiThread(new Runnable() {
#Override
public void run() {
tv_money_per_sec.setText(String.valueOf(money_per_sec));
tv_money_per_click.setText(String.valueOf(money_per_click));
toolbar_title.setText(String.valueOf(money));
}
});
}
}, 1000, 1000);
You have to check which Activity's life-cycle method are you using for starting your timer. I think you are using onResume which case this problem, and you start another timer by getting back to your Activity.
you can take a look at this diagram and choose the best position, or even separate your timer from activity life-cycle:
also you can implement Application class and place your timer there. this class is instantiated once during your application life time:
public class MyApplication extends Application{
private OnTimerTick listener;
public void setListener(OnTimerTick listener) {
this.listener = listener;
}
#Override
public void onCreate() {
super.onCreate();
// start your timer
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
money = loadGame.getInt("money", 0);
money_per_sec = loadGame.getInt("money_per_sec", 0);
money_per_click = loadGame.getInt("money_per_click", 0);
money = money + money_per_sec;
SharedPreferences saveGame = getSharedPreferences(SAVE, 0);
SharedPreferences.Editor editor = saveGame.edit();
editor.putInt("money", money);
editor.putInt("money_per_sec", money_per_sec);
editor.apply();
if(listener!=null)
listener.onTick(money,money_per_sec);
}
}, 1000, 1000);
}
interface OnTimerTick {
void onTick(int money, int moneyPerSec);
}
}
you have to add this to your manifest like this:
<application
android:name=".MyApplication"
...
also you can access this singleton class every where in your application:
MyApplication application = (MyApplication) getApplication();
inside your MainActivity:
public class MainActivity extends AppCompatActivity implements MyApplication.OnTimerTick {
private MyApplication application;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
application = (MyApplication) getApplication();
// other stuff
}
#Override
protected void onResume() {
super.onResume();
application.setListener(this);
}
#Override
protected void onPause() {
super.onPause();
application.setListener(null);
}
#Override
public void onTick(final int money, final int moneyPerSec) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tv_money_per_sec.setText(String.valueOf(moneyPerSec));
tv_money_per_click.setText(String.valueOf(moneyPerSec));
toolbar_title.setText(String.valueOf(money));
}
});
}
This is how you can even access the Timer within any other activity you like.
First, you should probably consider using a Handler instead of a Timer. This will allow you to more easily manage your Timer within the lifecycle of the Activity.
private final int interval = 1000; // 1 Second
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
public void run() {
Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
}
};
...
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);
Next, based on your comment:
I'm actually using onCreate in all other activities, but the fun part
is, that when I change activity, the timer still runs. And when I go
back to the activity that has the Timer, it "creates" another timer.
It looks like you are using the standard launchMode for your Activity. This launchMode will create a new Activity when the Back or Up buttons are pressed because the second Activity is creating an Intent to start that Activity.
Try setting the launchMode for the Activity with the Timer to android:launchMode="singleTop". This will instead route the Intent from the second Activity to the existing parent Activity, and trigger a call to onNewIntent. This will prevent the Activity from being restarted, and creating another Timer.
You should also probably terminate the Timer in the onDestroy method of your Activity, otherwise it will continue to run and could cause memory leaks.
Make your timer an instance of the activity rather than an anonymous class. Check if it is already running in onResume(). If not, start it. Stop it in onDestroy(). Something like this:
class MyActivity extends Activity {
private Timer mTimer;
#Override
public void onResume() {
super.onResume();
if (mTimer == null) {
mTimer = new Timer() {
};
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}
}

Android extended Timer

I want to know that can we create a single timer to handle two different background calls in different durations ? I have a code which updates the local time in my application in 30 seconds. What i want is to, not create any other timer but in the same timer, call a different function after 60 seconds. Here is my code
timer = new Timer();
timer.schedule(new RemindTask(), 10000,30000);
class RemindTask extends TimerTask
{
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
printMessage();// Current time
}
});
}
}
One solution can be:
class RemindTask extends TimerTask
{
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
count++;
if(count%120 == 0)
weatherApiCall();
printMessage();// Current time
}
});
}
}
Where count is a variable that allows you to know how many times the TimerTask was runned and to call the weatherApiCall one an hour.

Timer and TextView

I'm trying to understand how to use a timer.
In my MainActivity.class, inside on create method, i have this code
Timer timer = new Timer();
TimerTask updateM = new GestioneSlide();
timer.scheduleAtFixedRate(updateM , 1000, 5000); // i want to do a thing every second for 5 seconds
then i have another class where i override the method run, and where i want to write something in a texview that is in my MainActivity.class
class GestioneSlide extends TimerTask {
#Override
public void run() {
MainActivity.TextViewName.setText("bla bla");
}
}
My app crash, if i delete the MainActivity.TextViewName.setText("bla bla"); i have no problem. Probably i can't write in that textview that way
What did i do wrong?
The timer does not fire its actions in GUI thread. Use runOnUiThread to switch into it. Assuming GestioneSlide is the inner class of your Activity, write
class GestioneSlide extends TimerTask {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
MainActivity.TextViewName.setText("bla bla");
}
}
}
Make a Handler and show msg inside handler.
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_SHORT).show();
}
};

Create a Timer to send HTTP request Periodically - Android

I want to end HTTP request from a Android device to a web server and check a particular data of a database periodically (once a minute). I couldn't implement a timer for this.
Thanks
public class MyActivity extends Activity {
Timer t ;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = new Timer();
t.schedule(new TimerTask() {
public void run() {
//Your code will be here
}
}, 1000);
}
}
Try AlarmManager running Service. I wouldn't recommend sending request each minute thou, unless it's happening only when user manually triggered this.
TimerTask doAsynchronousTask;
final Handler handler = new Handler();
Timer timer = new Timer();
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
if(isOnline){// check net connection
//what u want to do....
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000);// execute in every 10 s
The most easy method is to loop a Handler:
private Handler iSender = new Handler() {
#Override
public void handleMessage(final Message msg) {
//Do your code here
iSender.sendEmptyMessageDelayed(0, 60*1000);
}
};
To start the loop call this sentence:
iSender.sendEmptyMessage(0);

Timer Not Stopping In Android

THE PROBLEM
I am having problems stopping the Timer whilst developing in android.
The timer is already null when it comes to stopping it.
I then move the timer initialisation to outside of a method just like the TimerTask which solves the null problem but still doesn't cancel when timer.cancel(); is called upon it.
The code below is an example of the timer already being null when it comes to stopping the recording.
TimerTask
My TimerTask is initialized inside the class but outside of a method and the codes below...
private TimerTask task = new TimerTask() {
#Override
public void run() {
Log.e("TRACK_RECORDING_SERVICE","Timer Running");
}
};
Timer & Timer Start
I then have a startRecroding method which is called when I want to start the timer...
public void startRecording(){
timer = new Timer("Message Timer");
timer.scheduleAtFixedRate(this.task, 0, 1000);
}
Timer Stop
I then call the below method when I want to stop the timer...
public void stopRecording() {
if (timer != null) {
timer.cancel();
timer = null;
} else {
Log.e("TRACK_RECORDING_SERVICE","Timer already null.");
}
}
Any help would be much appreciated.
timer = new Timer("Message Timer");
Here your object timer is not a static so timer.cancel(); will cancel another instance of the Timer class. I suggest you to create a static instance variable of Timer Class on the top of the class, like below,
private static Timer timer;
in the run() method, check if timer is null then
private TimerTask task = new TimerTask() {
#Override
public void run() {
if (timer == null)
cancel();
...
}
cancel the operation.
Ok so the problem was in the instantiation not the actual stopping of the timer.
Everytime I called:
timer = Timer()
timer!!.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
//something
}
}, delay, period)
It created another instance so the old instance was still running somewhere with no way to stop it.
So I just made sure to instantiate it when the timer is null so that no previous instance is getting pushed around and still running on the background.
if(timer == null) {
timer = Timer()
timer!!.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
// something
}
}, delay, period)
}
Then just cancel it and set it to null.
fun stopTimer() {
if (timer != null) {
timer!!.cancel()
timer!!.purge()
timer = null
}
}
if(waitTimer != null) {
waitTimer.cancel();
waitTimer.purge()
waitTimer = null;
}
I know it's late but I also encountered this issue in my project, and hope my solution may give people some ideas. What I did in my project is as below:
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
//TODO Update UI
}
};
public void stopTimer() {
if (timer != null) {
handler.removeCallbacks(runnable);
timer.cancel();
timer.purge();
timer = null;
}
}
public startTimer() {
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(runnable);
}
}, 0, 100);
}
I think what's missed in previous answers is removeCallbacks.
Try this example....
TimerTask mTimerTask;
final Handler handler = new Handler();
Timer t = new Timer();
int nCounter = 0;
//function for start timer
public void doTimerTask()
{
mTimerTask = new TimerTask()
{
public void run()
{
handler.post(new Runnable()
{
public void run()
{
nCounter++:
//your code
.....
......
}
});
}};
// public void schedule (TimerTask task, long delay, long period)
t.schedule(mTimerTask,0,50); //
}
//function for stop timer
public void stopTimerTask(){
if(mTimerTask!=null){
Log.d("TIMER", "timer canceled");
mTimerTask.cancel();
nCounter = 0;
}
}
//use above two function for start and stop timer.
Just in case if someone still comes here to find a solution to this problem, here is my experience.
I am running a timer in a service.
startForegroundService(mServiceIntent);
timer = new Timer();
When you refresh a service, you don't necessarily cancel it first, you just call startForegroundService(mServiceIntent); again.
If you don't cancel the timer before you refresh the service, the original timer is still running in the background and calling methods even though you stop the timer in the refreshed new service.
So to sum it up, stop your timer before you refresh or update a background task.
I hope it helps someone.
Though this is an old question, I've figured out an easy solution.
var timeTaskInstance : TimerTask ?= null
val task: TimerTask = object : TimerTask() {
override fun run() {
timeTaskInstance = this
Log.e("TRACK_RECORDING_SERVICE", "Timer Running")
}
}
Now cancel timer from anywhere:
timeTaskInstance?.cancel()
I think you've canceled another instance of the timer.
Your timer task would be better handled by a helper class.
public class TimerHelper {
Timer timer;
long InitialInMillis = 10 * 1000;
long DelayInMillis = 2 * 60 * 1000; // 2 minutes
public TimerHelper() {
timer = new Timer();
timer.schedule(new MyTimerTask(), InitialInMillis, DelayInMillis);
}
public void stopTimer() {
if(timer != null){
timer.cancel();
}
}
class MyTimerTask extends TimerTask {
#Override
public void run() {
// your task will be run every 2 minutes
yourTask();
}
}
}

Categories

Resources