I´m trying to improve my events handling system to make it more robust, improving precision stability.
Since the it´s a time based event handling/answering system, the first relevant decision would be which time reference to use. After reading everything I could find I ended up using SystemClock.elapsedRealtime().
Why not to use SystemClock.uptimeMillis() or System.nanoTime()? Because my system needs to keep working while in sleep/screen is off.
Any better approach here?
After that, the most problematic step: how to handle the timed events and guarantee they happen at desired time, without lags/delays/variations?
After reading as much as I could I decided to go for the handler approach, having one of them for each class of event (so different classes can happen asynchronously).
Unfortunately this isn´t working as expected:
- The timming sometimes gets perfectly synchonized and sometimes gets really big constant delays. without changing the code at all, just launching the application minutes after. Any clock synchronization issues between threads (event generator and event handler are in different threads)?
- The handler timming isn´t constant/precise and I can easely notice event results being displayed out of sync with a variable lag.
Any tips about how to handle timed events in a more precise way in Android?
Thanks,
Gabriel Simões
Related
I want to get the exact time that a button is pressed.
Of course I can use System.currentTimeMillis() in the onClick handler, but presumably there is a fair bit of processing that happens between the button physically getting tapped and the onClick handler getting called. I don't know if this is of the order of nanoseconds or milliseconds (say if a garbage collection is running), but I'm wondering if there is any accessible value that is stored earlier in the processing that I could reference.
I suspect the answer is no, but I thought I'd ask anyway. Perhaps there is some undocumented, but accessible value?
Many thanks!
I think there are no ways to do it, all UI controls work in the Main-thread, the signals from low-level drivers (overlay-driver) don't handling immediately and put in a special queue for handling on the Main-thread. I guess, you're trying to catch an interval between the physical click and the button event in your code, isn't it?
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
I do have a more general question, without any specific code. I will explain what my application does and how and what issues I can monitor. Maybe one of you had the same issues and can lead me to the problem.
The App:
It reads car diagnostic data (OnBoardDiagnostics) over Bluetooth and shows them in real-time in a ListView. I can start the update function by a "update Button".
How:
Everytime a new value is received via Bluetooth, a background Class (which handles the Stringforming) sends an Intentto notify the UI to update the ListView.
The Adapter Class of my ListView has the listening BroadcastReceiver registered and if it gets triggered, it will notify the ListView by notifyDataSetChanged().
Issues:
1.If I use an WakeLock to keep the screen on, the UI refreshing slows down after approx. 10 minutes.
2.If I press the power button, so the screen is off, it still slows down (I can see that, because I send the values to an webserver) but furthermore: If I turn the screen back on. I see the ListView stops for about 20-30 seconds and than normally continues with normal speed (not slow anymore).
So.. I think this is a very general question. I searched for WakeLock and sleep behaviour, but I couldn't find any similar issues. Maybe one of you can give me a hint, what the problem could be. Maybe one of you had a similar problem.
Any hint is appreciated!
EDIT 1:
Maybe the problem of the 2. issue is based on the lifecycles of my objects / activity.
If I press the update Button, an AsyncTask is started, which sends the Data (JSON, which contains one new value for all list items) to my Webserver. If the device screen is off, I still get the data every 2 seconds. If I turn on the screen, it stops for these 20-30 seconds as well as the UI. So I think my UI works fine. The Update Intents were sent right.
I have to check if I still receive new values in that background class, mentioned above.
Thanks to zapl
Thanks!
Except all possibilities I checked, i came across this article:
AsyncTasks for long running Operations
Short: There are some points you need to keep in mind if you are using AsyncTasks in very long running operations (>20min). My Problem was, that I used the AsyncTask as an inner Class. After a long period, when the Activity that created the Task was destroyed, the AsyncTask still kept a reference of this activity.
After I used a Bus, described in the article above, the UI worked fine!!
So, if anyone else noticed performance problems of your App, I recommend that article.
Thanks for all the other hints!
Have fun coding!
I am currently trying to write a simple application very similar to this:
http://lab.andre-michelle.com/tonematrix
My main problem is that I do not know how to handle the general program flow. Traditionally, I would use a loop inside the main function that handled the drawing and updated the state and everything. The way the android framework works is a bit confusing since the access points into the program are the various onSomething() functions. This is quite confusing for a beginner.
How do I keep track of time and how do I know how when to move to the next square column?
Do I HAVE to use threads? Is there a single thread solution, similar to the single loop approach?
You can use timers, they do already run in their own threads.
You can also use handlers for timed execution.
In case of the sample program u linked to, you would add something with onTouch and have a timer running in the background to periodically play the tune.
The activity lifecycle should be seen as the lifeline of your program not so much of the code in it.
How to keep track of time ?
System.currentTimeMillis();
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.