Inactivity is a very important EVENT. For many apps if the user does not interact with it for a certain number of seconds its time to reset the app and go back to main activity logout, or conserve power. So I would really like to get some feedback on the best way to detect this. In fact I think everyone will benefit from a good solution to this.
So my question is twofold:
1) Is there a better way to detect user inactivity than using a combination of
activity.onUserInteraction() to reset a CountDownTimer?
Note: One reported downside to this approach is that softkeypad interaction might not be
caught by this approach.
Note: Another reported downside is the CountDownTimer is off main thread and might not update
correctly. I am not sure how big an issue this is?
Note: CountDownTimer appears to have cancellation issues as well:
how to stop/cancel android CountDownTimer
2) Lets say that onUserInteraction()/CountDownTimer is the best/only solution to this problem
there are still some questions:
a) should each activity launch its own countdown timer?
b) Should a single countdown timer be restarted in the onCreate method of each activity?
c) lets say I want to dim the screen or goto main activity when the countdown expires where
should the timeout handler be located? In each activity? In a service?
Thanks
Just stumbled upon this question as I've answered something similar just now.
Personally, I'd opt for option 2 that you have suggested, and put a timer into a singleton so its available across all activities. Theres no need for a separate countdown timer unless you have a specific requirement to react different under different features of your application.
Why would you want to reset the timer in the onCreate? You should do that each time the user interacts with the application, such as in the activity.onUserInteraction() method.
To quote from my previous answer:
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.
Related
I'd like to know the code or configuration needed to set that.
In my app, there are some places where I'm willingly make the app to sleep for several seconds, as it's needed for some reasons, with a Thread.sleep(long millis) function.
Problem is that on some Android APIS, at least on 25 and 26, usually that system message pops up in few seconds, confusing the user and maybe even causing the application not to fulfill the needed operations that need to happen while that sleep is happening if the user ends the app, which might cause even malfunctioning of the application.
I'd like to find a way of either forcing Android to wait for a good time like, for example, 1 minute, or to make Android aware that it's not that app isn't responding, that is willingly on a Thread.sleep function.
Is there any way to do that?
I'd like to find a way of either forcing Android to wait for a good time like, for example, 1 minute, or to make Android aware that it's not that app isn't responding, that is willingly on a Thread.sleep function.
TL;DR there is none.
Android apps should at all times be able to yield their position in the foreground to other apps. It's up to the users if they want to wait while some lengthy download is taking place or if they prefer to do something else and come back later.
You can't execute Thread.sleep() on the UI thread for long because this would "freeze the UI".
An example: Users should be able to leave your app by pressing the BACK Button at any time they wish to. If your method is blocking the UI thread, Activity#onBackPressed() can't be executed so the users can't quit.
What can you do? Move the heavy work to another thread (using e.g. AsyncTask or IntentService or some plain worker thread) and show some type of progress indicator to the users if necessary. You can/ should also toggle visibility or enabled state of Buttons etc. if required to avoid clicks which can't be processed at that point in time.
I think you have an implementation problem. The system message, known as ANR (Application Not Responding) occurs when the application cannot respond to user inputs, this may be caused by Ui thread blocking and that may be your case.
To avoid blocking the UI Thread just run your long time operations asynchronously. There are many ways to do that. You could use AsyncTask, AsyncTaskLoader, Thread, RxJava... Here you have some links to help you with that:
https://developer.android.com/training/articles/perf-anr
https://google-developer-training.gitbooks.io/android-developer-fundamentals-course-concepts/content/en/Unit%203/71c_asynctask_and_asynctaskloader_md.html
http://www.vogella.com/tutorials/RxJava/article.html
if i want to run a timer for a long time in android and show the user, when they go to a particular activity, for example, the duration since the timer started as a live number - how should I implement this? By live, i mean the time shown changes in real time as one would expect a timer to do. There will only need to be one instance of this timer, it'll pretty much be like android's stopwatch but implemented to function within a custom app.
Would I require wakelock?
should I create a service?
or should I just use a simple java timer?
any help/advice much appreciated.
thank you.
What do you mean 'long timer' 1 minut, day?
You have to realise that android can kill you activity any time, so the activity is not the right place to do it.
You can run you operation in Service - his life is longer then activity's, but you probably want to check time even if user returns in activity after week or reboot device.
If you tell more info about what you want it'll be easier to solve you problem.
show the user, when they go to a particular activity
As I see you problem the solution should be like this:
First enter to the activity - create timer, start it,
On activity stop save current value of the timer and system time,
On recreate activity read saved value and start new timer with value of init_value + (current_time - saved_time).
In this case you can be sure that timer is persistant even if user left your activity and even restart device.
And also battery life will be much more longer :)
I have an Android application which depends on the value returned by a webservice. This value changes only once a week. Clients should detect this changed value, but the exact time they detect this change is not really important, 12 to 24 hours later should be no problem.
My current implementation starts an IntentService in the onCreate() method of my custom Application class which retrieves the value from the webservice. I also persist the last retrieved value in the SharedPreferences, so the application does not have to wait until this value is retrieved.
Now my question is if it is necessary to schedule the retrieval of this value after it's first retrieval in the onCreate() method, lets say after 12 hours. I know the onCreate() method is called only once in the lifecycle of an application, but I do not know how likely it is an application will be terminated by the Android system. Is it reasonable to assume that the application will be terminated enough times so that scheduling is not necessary? And in the case I should schedule the operation, what will be the best way to achieve this?
If you used onCreate(), I don't think you'd have any guarantees that it would be called a second time. E.g. if the user plugs their phone in to charge, has go-to-sleep turned off and leaves your app running for days on end. Very unlikely, but not impossible.
If I were you I'd set up some sort of scheduled task. Maybe this link will help:
http://developer.android.com/resources/articles/timed-ui-updates.html
The example uses an OnClickListener to cancel the task.
OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
};
You would want to put this elsewhere, in onDestroy() perhaps.
There are a couple of options, as I have had similar design challenges. Both have pros and cons.
Option A
You could have a splash screen, like many apps, and use the asyncTask class to make web requests and update your shared preferences. You could set a custom timeout so the app doesn't get stuck on the splash screen for too long. No matter what the result, if it updated or did not, you can then load what ever is in sharedPreferences and use that for app usage on that run.
The good thing about this is that every time the app starts you won't have to worry if the data is up to date or not, as you will just go and get it. For performance updates you could also store the last time the sharedPref value was updated (e.g. you got the value less than 12 hours ago) and therefore skip the web request - the result makes your splash screen quite quick to come and go.
Option B
You could use an Alarm via the AlarmManager, this is would be much better than a service which would be a unnecessary battery drain. There is even an enum for the interval of a day "INTERVAL_DAY". When the alarm is triggered a broadcast recevier will execute your custom code that would make the web request and get the values and store them. You can state if the Alarm repeats is a single use.
Hope that helps.
EDIT: there aren't the only options just the ones i picked out of relevance.
I would like to be able to detect if a user is inactive in my Android application for a specific period of time, if so I want to start a new activity where the user is asked for a password to resume using the application. The previous activity should start off where it was left.
Is this possible in an Android application? I am guessing I should start off a separate thread as soon as the application loads, which keeps checking for user activity, but how do I do that.
This is a very difficult question to answer without knowing details of your Application.
For example...how many Activities does the app have? What do those Activities do? What widgets (buttons, listviews etc etc) does each have?
For a start, to gauge whether a user is 'active' or not then you'd need to keep a 'last used' time field. Doing this however would mean keeping a static 'long' variable (either at the Application level or persisted through SharedPreferences if there is more than one Activity). The variable would hold the 'last used' time in milliseconds.
You would need to update this every time the user interacted with any Activity (touched, scrolled, clicked a button etc). Those interactions require different listeners which would each have to update the 'last used' time. More than that, you'd need each listener to test the 'last used' variable before updating it with the current time - if it was longer ago than 5 minutes (or whatever your timeout) then they'd need to raise an event to force a popup requiring the user enters the password.
This is all doable but it's complex.
Alternatively, you could simply set a countdown timer but you'd still need every touch, click or gesture to reset the countdown and it would still require doing this for every Activity in your app. Pretty much most of the above also applies.
Describing your app further might help someone provide a more concise answer.
I am doing an application in android which requires to know for how long the application is running. Do anyone know how to retrieve such information??. Is there any way where android provides the information about the running applications ,from how much time they are running??
I'm not aware of any method which would handle that but you can simply implement it yourself. Just capture the current time in seconds and in the onPause() method do the same. Then just subtract the first saved time value and the last saved value and you should know for how many seconds the application was running.
There might be another more elegant solution I don't know of tho.
You could user SystemClock.uptimeMillis() or SystemClock.elapsedRealtime() in your main activity once it is first launched. Then each time you need to see how long the app is running call the method again and subtract from the original value.
There is some data collected for all applications to show battery usage by application, but I've not done the research to find out how to access it programmatically (if even possible) and am not sure when it is reset (perhaps on every charger/usb disconnect).
For one application the previous suggestions about instrumenting create and pause/resume methods sounds best.