I am new to android.
Learning about the lifecycle of the activity.
I am having difficulty understanding the logic here.
There are three variables:
boolean running, wasRunning, and int seconds.
I am not able to understand the code inside onStop and onStart. Can someone please explain the logic of the code shared below that why are we using wasRunning?
public void runTimer()
{
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
running = true;
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
running = false;
}
});
reset.setOnClickListener(newView.OnClickListener() {
#Override
public void onClick(View v) {
running = false;
seconds = 0;
}
});
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds / 3600;
int min = (seconds % 3600) / 60;
int sec = seconds % 60;
String time = String.format("%d:%02d:%02d", hours, min, sec);
text.setText(time);
if (running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
#Override
protected void onStop() {
super.onStop();
wasRunning=running;
running=false;
}
#Override
protected void onStart() {
super.onStart();
if(wasRunning);
running=true;
}
This is actually very poor code. It keeps a continually running timer, and uses a flag to ignore it when not running. Instead, when the activity is stopped it should stop the timer to use fewer CPU resources. But here's what it does:
OnStop- when the activity is backgrounded, start ignoring timer events, and set a flag (wasRunning) to know whether it was running when it was last active.
onStart- if the timer was running last time the app was foregrounded, stop ignoring timer events.
So the combo of these two functions will ignore all timer events when in the background, but start listening to them again when it regains the foreground.
Related
i'm working with bunch of activities, i need to implement auto time out when my app is in inactivity state. my scenario is when i login my timer need to start if i didn't do anything after i logged in.
my timer need to start with last interaction with application,
my timer need to start when my app goes to background and screen off cases, and also
my timer need to stop when i log out from application.
i tried with below code from Here only:
public class MyBaseActivity extends Activity {
public static final long DISCONNECT_TIMEOUT = 300000; // 5 min = 5 * 60 * 1000 ms
private Handler disconnectHandler = new Handler(){
public void handleMessage(Message msg) {
}
};
private Runnable disconnectCallback = new Runnable() {
#Override
public void run() {
// Perform any required operation on disconnect
}
};
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();
}
}
But this code doesn't starts my timer when my app goes background or app screen offs, in those cases timer stopped.
Please give me ur valuable suggestions and help me for saving my time on things.Thanks all.
Need to detect whether the app is in background state or not
#Override
public void onStop() {
if (Constant.isAppIsInBackground(this)) {
stopDisconnectTimer();
resetDisconnectTimer();
}else {
stopDisconnectTimer();
}
super.onStop();
//stopDisconnectTimer();
}
Here isAppisBackground() is the method for detecting background state
i've created a small app of memory game. in that app i have created a timer that show the time that take the user to finish the game. my problem is that the timer freeze after i go to another page (like home screen) and back to the game- the time remain at the same time it was stopped.....(i khnow it related somehow to onRestarte() method but dont know what to do..) i want that the timer will continue at the same time it has been stopped. (like if the user have an incall in the middle of the game and then want to continue).
package com.example.kineret.memorygame;
public class Game4x4Activity extends AppCompatActivity implements View.OnClickListener{
TextView timerTextView;
long startTime = 0;
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timerTextView.setText(String.format("%d:%02d", minutes, seconds));
timerHandler.postDelayed(this, 500);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game4x4);
timerTextView = (TextView) findViewById(R.id.timerTextView4x4);
}
#Override
public void onPause() {
super.onPause();
timerHandler.removeCallbacks(timerRunnable);
}
#Override
public void onClick(View view) {
if(newGame) {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
newGame = false;
}
// rest of my code...
}
i have edited your code. plz try this
public class Game4x4Activity extends AppCompatActivity implements View.OnClickListener{
// make a new variable
static long elapsedTime = 0;
TextView timerTextView;
long startTime = 0;
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
// change here
long millis = (System.currentTimeMillis() - startTime) + elapsedTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timerTextView.setText(String.format("%d:%02d", minutes, seconds));
timerHandler.postDelayed(this, 500);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game4x4);
timerTextView = (TextView) findViewById(R.id.timerTextView4x4);
}
#Override
public void onPause() {
// change here
elapsedTime = elapsedTime + (System.currentTimeMillis() - startTime);
timerHandler.removeCallbacks(timerRunnable);
super.onPause();
}
#Override
public void onResume() {
super.onResume();
// change here
if(!newGame) {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
}
}
If the user gets a phone call your app will call onPause then if they finish their phone call and play your game your activity will get onResume called.
in onPause save the system time, in onResume get the latest system time. Take these away from each other (in onResume) and you will have the time that the user was not in your app, you can then add this to your timer before you restart it.
You may also have to persist this time with onSaveInstanceState at other points.
I have a button(in say Activity 1), which when clicked should start a service (eg Service 1). But there must be a delay of 5 seconds before the service starts. I achieved this using SystemClock.sleep(5000) in the onStartCommand of the service. This worked properly.
Now I want to add the functionality that if the button is clicked again(even before the 5 seconds end), the service WILL NOT BE STARTED.
Any ideas how to do this?
(Edit : Please read the entire question before marking it as a duplicate. Thanks)
You can use handler with post delayed to achieve your goal. Make your button disable and enable it after five seconds along with starting your service. You can implement the following code:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
button.setEnabled(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//start your service here
button.setEnabled(true);
}
}, 5000);
}
});
Above code will disable your button for 5 second and will start your service after 5 second.
I'd use a util class similar to the following. Pass it in a runnable and a delay in ms and you can call stop() on it to cancel before it has run. You can also call restart() if you want to restart your timer. I use it for things like auto showing/hiding controls on an immersive view.
public class DelayableRunnable{
int mDelay = 0;
Handler mHandler = new Handler();
Runnable mRunnable;
boolean mIsRunning = false;
public DelayableRunnable(Runnable runnable, int delay){
mRunnable = runnable;
mDelay = delay;
}
public void setNewDelay(int delay){
mDelay = delay;
}
public void start(){
if(mIsRunning) {
stop();
}
mHandler.postDelayed(mRunnable, mDelay);
mIsRunning = true;
}
public void stop(){
mHandler.removeCallbacks(mRunnable);
mIsRunning = false;
}
public void restart(){
stop();
start();
}
}
You can use Handler.postDelayed function for delayed actions in Android enviroment (better than plan java methods)
final Handler handler = new Handler(); // or use existed one your_view.getHandler()
handler.postDelayed(new Runnable() {
#Override
public void run() {
//start your service
}
}, 5000 /* 5s * 1000ms */);
Or simpler use you view function (work same as above):
your_view.postDelayed(new Runnable() {
#Override
public void run() {
//start your service
}
}, 5000 /* 5s * 1000ms */);
A facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals void schedule (TimerTask task,long delay) Schedules the specified task for execution after the specified delay.
new Timer().schedule(new TimerTask() {
#Override
public void run() {
alertDialog.dismiss();
startActivity(new Intent(****.this,*********.class));
}
},5000);
I have an app that does a small survey and as long as the app is open, it'll play a sound every 2 mins (to remind the user). But once the screen goes dark/app goes to back ground. It won't play the sound again.
How do I get it to repeat the sound, even when the app is in the background?. I tried calling the timer function in onStop() but that didn't work
private MediaPlayer mp;
Timer timer;
TimerTask timerTask;
final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mood);
addListenerOnNext();
mp = MediaPlayer.create(MoodActivity.this,R.raw.sound);
radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
nextbutton = (Button) findViewById(R.id.nextbutton);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if (radioGroup.getCheckedRadioButtonId() != -1)
{
nextbutton.setEnabled(true);
}
}
});
}
#Override
public void onStart()
{
super.onStart();
startTimer();
}
#Override
public void onStop(){
super.onStop();
}
#Override
protected void onResume(){
super.onResume();
startTimer();
}
public void startTimer(){
//set a new Timer
timer = new Timer();
//initialize the timer task
initializeTimerTask();
timer.schedule(timerTask,500,120000);
}
public void stopTimerTask(){
if(timer != null){
timer.cancel();
timer = null;
}
}
private void initializeTimerTask() {
timerTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
mp.start();
}
});
}
};
}
Check out this link.
It describes how to keep screen awake, while your application is running.
I will suggest to use backgroung service which will run periodically.
Check out this link
Run Service periodically
Where do i start?
You have 2 acceptable ways to continue performing actions while your application is not in the foreground (especially for periodic tasks); (started) Service and AlarmManager.
The started (rather than bount) Service has its own process which will remain alive even when you're app is not in the foreground which means you could use a Thread, Handler etc. (*NOT TimerTask) to perform repeating tasks no matter what happens.
The AlarmManager uses a system Service to start PendingIntents no matter if your application is alive or not.
As for TimerTask, there are many posts online stating why it is a poor choice for Android development, here's one example, please use IntentService, AsyncTask, Loaders, Handlers or almost anything else.
I am developing an application that will be running in Kiosk Mode. In this application, if the user didn't do anything in the application within 5 minutes, the application will show a screen saver that is the logo of the application.
My question is, how can I code on detecting IDLE within 5 minutes?
A BETTER SOLUTION HERE...... VERY SIMPLE
I used countdown timer as bellow:
private long startTime = 15 * 60 * 1000; // 15 MINS IDLE TIME
private final long interval = 1 * 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
countDownTimer = new MyCountDownTimer(startTime, interval);
}
#Override
public void onUserInteraction(){
super.onUserInteraction();
//Reset the timer on user interaction...
countDownTimer.cancel();
countDownTimer.start();
}
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
//DO WHATEVER YOU WANT HERE
}
#Override
public void onTick(long millisUntilFinished) {
}
}
CHEERS..........:)
You should try this, It will Notify with a toast on detecting IDLE 5 minutes.
Handler handler;
Runnable r;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
r = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "user Is Idle from last 5 minutes",
Toast.LENGTH_SHORT).show();
}
};
startHandler();
}
#Override
public void onUserInteraction() {
// TODO Auto-generated method stub
super.onUserInteraction();
stopHandler();//stop first and then start
startHandler();
}
public void stopHandler() {
handler.removeCallbacks(r);
}
public void startHandler() {
handler.postDelayed(r, 5*60*1000);
}
I think you could use http://developer.android.com/reference/android/app/Activity.html#dispatchTouchEvent(android.view.MotionEvent) and http://developer.android.com/reference/android/app/Activity.html#dispatchKeyEvent(android.view.KeyEvent) in your App to set a timestamp everytime a userinteraction takes place (simply override the methods and return false at the end so that the events will be propagated to underlying views) - then you can use some kind of timer which checks for the last timestamp of interaction recurringly and trigger your screen saver if your 5 minutes IDLE time are reached.
So in an Activity you simply override the before mentioned Methods like this:
#Override
public boolean dispatchTouchEvent (MotionEvent ev) {
timestamp = System.getCurrentTimeMilis();
return false; // return false to indicate that the event hasn't been handled yet
}
The dispatchKeyEvent and the other methods which you can override to determine user-activity should work fairly similar.
If you're using more than one Activity you may want to create a base class which extends Activity and Override all the dispatchXXXEvent you want to handle and which you than use as base class of all your Activities. But I guess the details of your implementation may be a little bit out of scope for the actual question :)
For the different possibilities of timers you may find useful info here: Scheduling recurring task in Android
try with:
private void startCount(int time) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Add here the code for showing the fullscreenlogo
}
}, time);
}
then, whenever you want to start the count you should add:
startCount(time); // Replace time with 60*5*1000 for 5 mins
if you want to start the count when the app got minimized, then use this:
#Override
public void onPause() {
super.onPause();
startCount(time);
}