Timer mytimer = new Timer();
int i = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mytimer.scheduleAtFixedRate(new TimerTask()
{
#Override
public void run () {
runOnUiThread(new Runnable() {
#Override
public void run() {
i++;
}
});
}
},0,1000);
Here is my code, after I ran the app on background for few minutes and returned to the app. The app started another timer (sometimes it doesn't starts) and there were two timers running. Please tell me how do I prevent it.
Related
I'm a beginner in Android programming. I'm trying to display a timer for an upgrade in my game to show how long the upgrade will be activated for. In my collision flag I call Looper.prepare and start my thread class as the logcat suggested I do. How would I get this to run on one looper?
Here is the snippet that starts the thread.
BigGapUpgrade.java
public boolean playerCollectUpgrade(Player player){
if(Rect.intersects(rectangle, player.getRectangle())){
Looper.prepare();
bigGapUpgradeHandler.start();
}
return Rect.intersects(rectangle, player.getRectangle());
}
And here is my thread class
BigGapUpgradeHandler.java
public class BigGapUpgradeHandler extends Thread {
TimerTask scanTask;
Timer timer = new Timer();
#Override
public void run() {
Looper.prepare();
scanTask = new TimerTask() {
public void run() {
}
};
timer.schedule(scanTask, 0, 4000);
CountDownTimer countDownTimer = new CountDownTimer(4000, 100) {
#Override
public void onTick(long l) {
Log.i(TAG, "onTick: ");
}
#Override
public void onFinish() {
timer.cancel();
Log.i(TAG, "onFinish: ");
}
}.start();
Looper.loop();
}
}
After running it I get this error
W/System.err: java.lang.RuntimeException: Only one Looper may be created per thread
--Edit
Here is the solution I came up with.
-- Solution
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
CountDownTimer countDownTimer = new CountDownTimer(5000,100) {
#Override
public void onTick(long millisUntilFinished) {
millis = millisUntilFinished/100;
}
#Override
public void onFinish() {
}
}.start();
}
});
OK, So what you can do is just use a TimerTask. That creates it's own background thread for you do stuff:
// This TimerTask Updates the UI so it needs a reference to the Activity.
static class PowerUpTimerTask extends TimerTask
{
WeakReference<AppCompatActivity> mActivity;
long mInterval;
long mPeriod;
public PowerUpTimerTask(AppCompatActivity activity, long period, long interval)
{
mActivity = new WeakReference<>(activity);
mInterval = interval;
mPeriod = period;
}
#Override
public void run()
{
AppCompatActivity activity = mActivity.get();
if (activity != null)
{
final TextView timerTextView = activity.findViewById(R.id.timerTextView);
mPeriod -= mInterval;
if (mPeriod > 0)
{
// Set time remaining
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
timerTextView.setText(String.valueOf(mPeriod));
}
});
}
else
{
// Out of time...clear the Text and stop the timer task.
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
timerTextView.setText("");
}
});
Log.d(TAG, "Timer done. Canceling.");
cancel();
}
}
else
{
// Cancel this timer task since we don't have a reference to
// the Activity any more.
Log.d(TAG, "Lost reference to Activity. Canceling.");
cancel();
}
}
}
Then you can start your Timer task like so:
...
// Will count down from 10 by 1s.
mPowerUpTimerTask = new PowerUpTimerTask(this, powerUpTime, 1);
// Schedule for every second.
Timer t = new Timer();
t.scheduleAtFixedRate(mPowerUpTimerTask, 1000, 1000);
...
Here is a link to this running sample:
https://github.com/didiergarcia/TimerTaskExample
I think you have to use LocalBroadcastManager for the timing to continuously in loop. Please check below code for for that :-
private void startTimer() {
countDownTimer = new CountDownTimer(Constant.getInstance().ANSWER_TIME_IN_SECOND * 1000, 1000) {
public void onTick(long millisUntilFinished) {
remaininTimeInMillies = millisUntilFinished;
tvTimer.setText(getTime(Integer.parseInt(String.valueOf(millisUntilFinished))));
}
public void onFinish() {
Intent intent = new Intent(Constant.getInstance().TIMER_RECEIVER);
LocalBroadcastManager.getInstance(PatientDetailActivity.this).sendBroadcast(intent);
}
};
countDownTimer.start();
}
private String getTime(int milliSec) {
int minut = 0, second = 0;
minut = milliSec / 60000;
second = (milliSec - (minut * 60000)) / 1000;
String strMinute = "", strSecond = "";
if (minut < 10) {
strMinute = "0" + String.valueOf(minut);
} else {
strMinute = String.valueOf(minut);
}
if (second < 10) {
strSecond = "0" + String.valueOf(second);
} else {
strSecond = String.valueOf(second);
}
return strMinute + ":" + strSecond;
}
#Override
protected void onResume() {
LocalBroadcastManager.getInstance(this).registerReceiver(timerBroadcast, new IntentFilter(Constant.getInstance().TIMER_RECEIVER));
super.onResume();
}
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(timerBroadcast);
super.onDestroy();
}
Thanks and Hope that will help you
So basically, I am making an application which at the touch of a button generates a sound for 1 second after every 10 seconds and simultaneously records all other sounds as well.
I want the sound recording to happen in that 10 second pause. I tried to use threads and thread interrupts for this. But don't really know how to use them properly for this case.
Here is my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playButton = (Button)findViewById(R.id.button);
textView = (TextView) findViewById(R.id.textView);
playButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Sound Gen Thread
Runnable myRunnable = new Runnable() {
#Override
public void run() {
new Timer().scheduleAtFixedRate(new TimerTask() {
public void run() {
AudioTrack tone = generateTone(freq, 1000);
tone.play();
}
}, 0, 10000);
}
};
new Thread(myRunnable).start();
//Recording Thread
Runnable myRunnable1 = new Runnable() {
#Override
public void run() {
doInBackground();
}
};
new Thread(myRunnable1).start();
}
});
}
I am implementing an inactivity timer based on this answer: https://stackoverflow.com/a/12481918/6298161
I need the timer to work across multiple activities, so as the comments suggest from the original post I have change the Handler and Runnable to be static.
How do I now redirect to a new activity in the runnable where I have put the comment? Any help is greatly appreciated
public class InactivityTimerActivity extends AppCompatActivity {
public static final long DISCONNECT_TIMEOUT = 300000; // 5 min = 5 * 60 * 1000 ms
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inactivity_timer);
}
private static Handler disconnectHandler = new Handler() {
public void handleMessage(Message msg) {
}
};
private static Runnable disconnectCallback = new Runnable() {
#Override
public void run() {
// I want to redirect here
}
};
public void resetDisconnectTimer() {
disconnectHandler.removeCallbacks(disconnectCallback);
disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
}
public void stopDisconnectTimer() {
disconnectHandler.removeCallbacks(disconnectCallback);
}
#Override
public void onUserInteraction() {
resetDisconnectTimer();
}
#Override
public void onResume() {
super.onResume();
resetDisconnectTimer();
}
#Override
public void onStop() {
super.onStop();
stopDisconnectTimer();
}
}
I think you shouldn't make it static. Just keep that protected, and then when start new activity, putting an integer variable inside the intent (the remaining time or the time that the timer has run). Then when on create new activity, you get that value out and set your timer base on that value.
Sorry for my english. I have timer and i wand if i click timer is on if i click again timer off. But my timer on only one time. If i click again(off timer) i have exception like this:
E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalStateException: Timer was canceled
at java.util.Timer.scheduleImpl(Timer.java:561)
at java.util.Timer.schedule(Timer.java:481)
at installation.ConnectDevice.callAsynchronousTask(ConnectDevice.java:211)
at installation.ConnectDevice$1.onClick(ConnectDevice.java:153)
at android.view.View.performClick(View.java:4240)
...
I dont know why its not work, please help. Below my class
My class
private Timer timer;
int time = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.i_connect_device);
timer = new Timer();
// my botton
includeDevice.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (time < 1) {
callAsynchronousTask();
time++;
}
if (time > 0) {
stopTimer();
time--;
}
}
});
}
public void callAsynchronousTask() {
final Handler handler = new Handler();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
Log.e("Timer is work", "Timer is work");
// GetMsgs performBackgroundTask = new GetMsgs();
// PerformBackgroundTask this class is the class
// that extends AsynchTask
// performBackgroundTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 1000 * 10); // execute in every
// 50000 ms
}
public void stopTimer() {
timer.cancel();
}
Change onClick logic as follows (because in your case at the first time only executed callAsynchronousTask() and stopTimer(). so it raises exception at next onClick)
btnTimer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (time == 0) {
callAsynchronousTask();
time = 1;
} else {
stopTimer();
time = 0;
}
}
});
and doAsynchronousTask make it as field and cancel task on stopTimer().
public void stopTimer() {
doAsynchronousTask.cancel();
}
then it works fine.
From Javadocs:
cancel() : Terminates this timer, discarding any currently scheduled tasks. [...] Once a timer has been terminated, its execution thread terminates gracefully, and no more tasks may be scheduled on it.
and
schedule(Task task, long delay)
throws:
IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
So basically, your class tells you that it cannot complete the set task due to the fact that the timer has been cancelled. Something you could try is to make the timer sleep until the button is pressed again, instead of cancelling it completely.
Once you cancel the timer; you cannot start it again because thread is stopped.See the link:Pause the timer and then continue itYou have to maintain the state somehow and recreate timer with the current value
You need an async task it is a class so you can extend it. Public class callAsynchronousTask extends async task
And GetMsgs performBackgroundTask = new GetMsgs();
// PerformBackgroundTask this class is the class that extends Async Taskbar goes into the do in background method
Initialize your timer object inside callAsynchronousTask as shown below.
public void callAsynchronousTask() {
final Handler handler = new Handler();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
Log.e("Timer is work", "Timer is work");
//GetMsgs performBackgroundTask = new GetMsgs();
// PerformBackgroundTask this class is the class that extends AsynchTask
//performBackgroundTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer=new Timer();
timer.schedule(doAsynchronousTask, 0, 1000*10); //execute in every 50000 ms
}
Also modify your in block because it is executing both if condition .
Use boolean flag instead of int
boolean isTimerRunning;
if (!isTimerRunning) {
callAsynchronousTask();
isTimerRunning=true;
}
else (isTimerRunning) {
stopTimer();
isTimerRunning=false;
}
I have a text view in my android activity, and I want to pass it to a function in another java class and modify its text. But it throws me an exception. I read that I need to run it on a UI thread or send to context variable, but I'm a bit confused and I couldn't manage to do it. That's my code:
Java timer class
public class CountdownTimer {
static int duration;
static Timer timer;
public static void startTimer(final TextView TVtime) {
duration = 10;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
TVtime.setText(setDuration());
}
}, 1000, 1000);
}
private static String setDuration(){
if(duration == 1)
timer.cancel();
return String.valueOf(--duration);
}
}
Android activity:
TVtime = (TextView) findViewById(R.id.textView_displayTime);
CountdownTimer.startTimer(TVtime);
You cannot update the UI from a non-UI Thread. Pass the activity Context to the startTimer() method.
public static void startTimer(final TextView TVtime,final Context activityContext) {
duration = 10;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
((Activity) activityContext).runOnUiThread(new Runnable() {
public void run()
{
TVtime.setText(setDuration());
}
});
..........................
.......................
Android activity:
TVtime = (TextView) findViewById(R.id.textView_displayTime);
CountdownTimer.startTimer(TVtime, YourActivity.this);
You can use android.os.Handler for that :
public static void startTimer(final TextView TVtime) {
duration = 10;
final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
TVtime.setText((String) msg.obj);
}
};
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Message msg = new Message();
msg.obj = setDuration();
handler.sendMessage(msg);
}
}, 1000, 1000);
}