I have one activity. OnCreate the activity gets the source (html) of a web page to a string and presents the result (after parsing it a bit) in a textview.
I would like the activity to reload/refresh periodically to always present the latest information.
What is the best solution for this?
First of all... separate the updating logic from your onCreate method. So, for instance, you can create an updateHTML().
Then, you can use a Timer in order to update the page periodically:
public class YourActivity extends Activity {
private Timer autoUpdate;
public void onCreate(Bundle b){
super.onCreate(b);
// whatever you have here
}
#Override
public void onResume() {
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
updateHTML();
}
});
}
}, 0, 40000); // updates each 40 secs
}
private void updateHTML(){
// your logic here
}
#Override
public void onPause() {
autoUpdate.cancel();
super.onPause();
}
}
Notice that I'm canceling the updating task on onPause, and that in this case the updateHTML method is executed each 40 secs (40000 milliseconds). Also, make sure you import these two classes: java.util.Timer and java.util.TimerTask.
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
In the onCreate() method of my activity I have a Timer + TimerTask that will schedule a ParseQuery. On The ParseQuery callback, which is on mainThread, I delegate an interface callback to make a simple UI update. This works when I let the Activity unchanged. But if I exit from the activity and enter again it (A new timer will NOT be created here, because it gets created only when starting the activity from a certain point) wouldn't work. I think is something with Activity instances but I cannot handle it.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
....
uiTimer = new Timer();
uiTask = new TimerTask() {
#Override
public void run() {
doParseTask();
}
};
uiTimer.schedule(uiTask, shortCodeLeft);
}
doParseTask(){
Utils.doParseQuery(this, new MyListener{
#Override
public void onSuccess() {
updateUI();
}
});
}
updateUI(){
Log.i(TAG, "Show changed layout"); //This is always shown, this way I ensure it gets here!!
mTextView.setText(foo); //this doesn't work
mLayout.setVisibility(View.GONE); //this doesn't work
}
The ParseQuery is executed in done() callback method, I call the function that updates the UI:
public class Utils{
.......
doParseQuery(Context ctx, MyListener listener){
.......
query.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e == null){
....
listener.onSuccess();
}
}
});
}
}
What I have tried, with no success:
1. make the `uiTimer` and `uiTask` static global variables; // I thought that maybe it gets leaked into activity instances
2. update the UI using
runOnUiThread(new Runnable() {
#Override
public void run() {}
});
OR
mLayout.post(new Runnable() {
#Override
public void run() {
mLayout.setVisibility(View.GONE);
}
});
3. android:launchMode= "singleInstance" //in Manifest
If you want that your UITimer to gets executed every time your activity goes to foreground, you should implement the onStart or onResume method and move your uiTimer implementation to one of both method. Even your activity being already started these two methods are called after exiting the activity and reopening it again.
A better explanation of Android Activity lifecycle is well explained by google documentation https://developer.android.com/guide/components/activities/activity-lifecycle.html.
Your code would look like this:
#Override
protected void onStart() {
super.onStart();
....
uiTimer = new Timer();
uiTask = new TimerTask() {
#Override
public void run() {
doParseTask();
}
};
uiTimer.schedule(uiTask, shortCodeLeft);
}
doParseTask(){
Utils.doParseQuery(this, new MyListener{
#Override
public void onSuccess() {
updateUI();
}
});
}
When you exit from your activity, the instances mTextView and mLayout will be destroyed.
Then, when you create a new activity, the activity creates new instances of the text view and layout.
Your timer goes off and tries to update the original elements, which are now invalid as the activity has been closed (but the log still works as this is separate to your activity).
You should initialise the timer & task in onCreate(), and then in order to stop updating the old UI elements:
#Override
protected void onStop() {
if (uiTimer != null) {
uiTimer.cancel();
}
super.onStop();
}
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;
}
}
}
In this code value of the shared preference will be assigned after this activity is launched.I want this code to continuously listen to the change in the shared preference value and upon change an activity to trigger.But the code on execution throws an error saying Null pointer.
Thanks Varanasi
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.d_pay);
con=dpay.this;
sh=getApplicationContext().getSharedPreferences("CRUZER_PREF", MODE_PRIVATE);
getActionBar().setHomeButtonEnabled(true);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public void onResume() {
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
updateHTML();
}
});
}
}, 0, 40000); // updates each 40 secs
}
private void updateHTML(){
p=sh.getString("p", null);
Log.e("p", p);
// your logic here
}
#Override
public void onPause() {
autoUpdate.cancel();
super.onPause();
}
I think that having a timer that checks the preferences is a bit wasteful. Assuming that you have access to all the code that changes your SharedPreferences, what you can do is create a wrapper class around SharedPreferences, let's call it PrefHelper. In PrefHelper you'll have a method called setMySpecificPref(context, your parameters here). Anywhere you need to change that preference, you call that method. That method will then change the preference and launch your desired activity.
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);
}