I am trying to write to a file whenever the user has not interacted with the application for 2 minutes. Currently am having base activity in which I have overriden the onUserInteraction method. In this method the float time variable is reset and onResume I subtract the time with the current time to check if two minutes have passed. This works fine but sometimes acts crazy. Second approach was using the postDelayed method of the Handler and start a thread. This works perfectly but does not include the case when the app goes to background or the device goes to sleep.Is there a way to cover all these cases. ahve researched a lot. Also came across Wakeful Intent service but read that it is expensive.
Is there a way to cover all these cases.
Yes. ... and it is expensive. Waking the phone up, every 2 minutes is going to drain the battery like crazy.
That said, the answer to your question is that you need to use the AlarmManager, probably in concert with either the WakefulIntentService or the WakefulBroadcastReceiver. Create a PendingIntent and schedule it for delivery every 2 minutes.
I don't know a way of tracking inactivity but there is a way to track user activity. You can catch a callback called onUserInteraction() in your activities that is called every time the user does any interaction with the application. I'd suggest doing something like this:
#Override
public void onUserInteraction(){
MyTimerClass.getInstance().resetTimer();
}
If your app contains several activities, why not put this method in an abstract super class (extending Activity) and then have all you activities extending it.
Related
I need to calculate the time taken by my app to start. Do you have any ideas when to start and when to stop timing?
Use your timer at the beginning of oncreate() and stop it at the end of onResume().
According to lifecycle of an Activity.
To do this, you probably should be clear on what "start my app" means - if you are referring to an activity, then you should probably override the Activity constructor (not "onCreate" except in most cases there isn't any measurable time from the constructor before onCreate is called) and capture:
SystemClock.upTimeMillis()
then you need to create a listener for onGlobalLayout to determine when the activity is actually finished displaying on the screen and get the upTime again. For the listener, do it like in this post:
Activity lifecycle - receiving notification that layout is complete
And then take the difference between the times... however, that is really the "activity" startup time.
If you are certain your app is not running, and you want to see how long it takes to "start your app" when it is not loaded in memory at all, you should extend the Application class:
public class MyApp extends Application {
public MyApp() {
// get the time
}
}
and then override the constructor to capture the timestamp like above and store it. Your app's application class is constructed first, then activities are instantiated.
Then capture the listener time in the first activity to display, as mentioned above. That will probably tell you best how much time it took from when your app "starts" to when the user actually could see it.
There are a few things that happen between when a user action occurs that is intended to "start your app" that are not included, but you have no control over that, even though that should be included if you are trying to measure how long it takes from the user's perspective.
what would be the best way to continue the current Activity once its internal BroadcastReceiver onReceived has been called.
is it possible to start another thread from within the onReceived() method, and also can I start a AsyncTask inside the onReceived() ?
is it possible to start the same activity again from within the onReceived method?
thanx
Please note that an Activity does not survive a screen orientation change -- it gets re-created along with the View hierarchy. From the MVC viewpoint, an Activity is a Controller. Data that must survive an orientation change must go to the Model.
If you keep a reference to the Activity that has gone from the screen due to orientation change, that's a resource leak, and if the Activity receives the result of some AsyncTask, that's also a waste of CPU time and battery power.
Having said that, Activity defines runOnUiThread (Runnable action) which most likely is not what you really need, but it will at least work.
I mean, after the receiver's method is called, the normal cycle continues (reaction on events etc.), so you just need to react on the event reported to your BroadcastReceiver and reach the closing brace of the function.
If you ask if you can rely on that the same instance of SomeActivity will be shown when a long operation completes, the answer is no. For example, the user starts a long operation, then changes the screen orientation. The first SomeActivity, the one that started the long operation, will not be shown when the long operation completes.
I have a bunch of activities tied together, one into the next and so on. Now during one activity I want to measure elapsed time. As I understand, I would use System.nanoTime() to find the start time, the user does some things, then use it once more to find the end time, subtract the two and voila my elapsed time spent on the activity. But suppose something happens while my activity is running: I already have created the start time, but now the user gets a phone call or something, my activity is put into the background. The phone call ends and the user returns to the activity. Was the timer running the whole time, even while the app was in the background? Is the timer 'reset' since I left the app then came back to it?
Also, when I do initiate System.nanoTime() is it returning the time since the start of that particular activity or the main activity?
EDIT: Suppose I set the first tickmark at a certain point, then the app goes into the background, then it returns to the foreground and I set the second tickmark. Ideally I want the time elapsed along with the time spent in the background; does System.nanoTime() achieve this?
static long nanoTime():
Returns the current timestamp of the most precise timer available on the local system.
You aren't using a "Timer" (that is, a stateful object of any kind) to represent the elapsed time, you are just hanging on to a long. As you pointed out, you will call System.nanoTime() again at some future point and subtract to find the elapsed time.
If you want to exclude time spent outside of this activity, like the example in your question, you will need to use onPause() and onResume() to help you manage the calculations. Or, if you switch to some kind of timer object, use these methods to pause and resume the timer.
You can "start" your "timer" wherever you think makes the most sense. If it's when the user initiates some action (like a button press), od it in an OnClickListener. If it's just to measure how long some method/code path runs, do it at the beginning of that.
according to the doc
System.nanoTime() returns the current value of the most precise
available system timer, in nanoseconds.
So it is not an timer. It just returns the system time in nano seconds. It has not relation with activity.
If you want to measure the lifetime of activity then get the time in onCreate and onDestroy. And if you want the time to know how much time the activity was in foreground then get the time in onResume and onPause.
You will need to override onPause() and onResume() methods in the Activity class so you can pause your timer in pause. and resume in onResume.
You should put System.nanoTime() on onResume()
I am writing an Android app (ICS) for a tablet. The user moves from Activity A to Activity B to Activity C with the touch of a button. I want to return from Activity C to Activity A after 10 seconds. Is there some way to count to 10 without locking up Activity C?
I've succeeded with an asyncTask but if I startActivity(A) in the onPostExecute() it feels like I'm violating the guideline that an asyncTask should not mess with the UI. I've tried get() but that does lock up Activity C while it's waiting for the 10 seconds to pass.
Thanks in advance!
Assuming you have any View instance in your activity, you can use View.postDelayed() to post runnable with a given delay. In this runnable you can call Activity.finish(). You should also use View.removeCallbacks() to remove your callback in onDestroy(), to avoid your callback being called after user already navigated back from your activity.
Using AsyncTask just to count some time is just an overkill (unless you want to use AsyncTask to actually do some useful, background work). The Looper and Handler classes provide everything you need to execute any code on UI thread after a given delay. The View methods mentioned above are just convenience methods exposing the Handler functionality.
Using AsyncTask works fine as you describe. From Android Documentation:
onPostExecute(Result), invoked on the UI thread after the background computation finishes.
Since it is invoked on UI thread you should be fine.
Documentation
You can use a alarm manager for that. Set it to send a broadcast 10 seconds starting from activity a and implement a base activity for activity a b and c to receive the broadcast, after receiving the broadcast just end the current activity and start activity a with a new flag. If the current instance is activity a then ignore if not start activity a. Something like that.
As for the idle part you can update the alarm manager on every action, upon entering activity etc.
The advantage of this implementation is that you dont have to go through the hassle of having to worry about context leaks, persisting timers across activities and such. and can make use of what is already there. You can also consider using a service though.
If not you can just use the shared preference store the time to time out and check or update against it for the actions.. A simpler implementation.
Good luck.
I guess, I have a generic logic problem. I want to logout a user after 15 if there is no activity. How do I find any "activity" in android. How should I go about it...
Experts please help...
You'll need to invest a little thought into exactly what your requirements are here, but from what I can tell, you want to keep track of the user interactions and if a time limit expires since the last interaction, perform some action, in your case logging them out of your application.
Firstly, you'll need some place that you can track when the last interaction occured, since you'll want this to be application wide you could use a singleton to hold this, or override the Application class, either way should do.
Next, you'll need to start tracking user interactions. From your activities, you can override the onUserInteraction method, this gets invoked anytime the user interacts with the application such as key event. Each time you hit this method, update your singleton and let it know something has happened, with a timestamp.
Finally, you'll need some kind of looping check to constantly check if anything has happened recently. Theres various was of doing this, you could have a continuous loop that compares current timestamp to the last recorded event, a bit of draft code :
while(true)
{
if (timeLastEventRecorded < (now - 15))
{
//nothing has happened in 15 minutes, so take corrective action
}
}
Presumably you'll already have some code in your application that takes care of logouts, such as when the user clicks "logout", you should just be able to invoke that in the sample above.
Hope this helps
You should have all activities inherit from a parent activity that overrides onUserInteraction(). In that callback you should reset a static app wide timer that will perform your logout code when the time reaches the end.