Currently have stopwatches running on multiple devices that are kept in sync via a socket server. When a device starts the stopwatch it sends a message to the socket server, and the other clients listening see this and also start their stopwatch. There is not a huge amount of latency so it's not a big deal that while they are running the times are slightly off from each other.
However when "pause" or "stop" is pressed we want to have that final time shown on the pausing clients device to also be the same time shown on all devices.
Currently here is what happens when the timer is stopped/paused:
long time = Long.parseLong(message);
mChronometer.setBase(time);
The message being sent is from the code here:
this.sendWebRequestStopTimer(mChronometer.getBase())
While this does cause the time to be adjusted, it is slightly off usually by less than a second, typically 100-400 milliseconds. I assume this is because the each device has a slightly different time despite same NTP servers.
So in short, is there a better way to adjust the code so that the child devices will display the exact same time as the parent device (one who hit pause)?
Note: Any of the devices can play/pause/stop the stopwatch. No one device is in charge of controlling this stopwatch function. So device 1 could start the timer, device 2 could pause it, and device 3 could resume it.
Have the device that presses pause/stop send its time to the server, and echo that to all other devices. There's really no other way of doing it, short of a hard wired dedicated network. And even that would still leave you with some discrepancy in the 10s of ms range. Of course this could cause some of the devices to show a smaller number, looking like it went back in time. No real way to avoid that.
Related
First time asking a question. I appreciate any thoughts/feedback you may have.
Part of the functionality of an app I am working on requires that an internal counter in the app be in perfect sync with a counter on a remote server.
More specifically, there are 86,400 seconds in a day. Assume on a server I start a counter that ticks from 1 to 86,400 progressing at one tick a second. When it gets to 86,400 it starts over at 1. This then repeats indefinitely.
Part of the functionality of the app is the first time it is launched by the user it will connect to the server and sync a similar running counter within the app to perfectly match the counter on the server. (e.g. at the exact same time that the server counter ticks to perhaps 10,215.....so should the app counter be ticking to 10,215.)
Assume perhaps thousands of users have the app. I need it so that the thousands of individual app users now have 1 - 86,400 counters all running exactly in sync with each other. With the idea that a user only has to have their app perform this server sync a single time. After it's synced, the counters within the apps would then run in unison in perpetuity.
Questions:
1) Is this feasible to do? For the reasons I need this to occur, it literally cannot be off by even a second or two. They all have to match perfectly.
2) Would varying internet and/or phone speed by user be a problem (during the sync process)? Again, it is a one time sync. It does not have to sync on a continuous, real-time basis. Nonetheless, the first sync does have to be perfect.
3) If the answer to the above is that it is doable.....getting greedy here, can I sync it at even faster speeds? Instead of the counter just counting up one tick per second (i.e. 86,400 ticks per day), can the counter tick at perhaps a rate of 1/10 of a second (864,000 ticks per day). At that super fast tick speed, could the perfect sync still be accomplished?
While not the exact reason for needing the above, to give perspective.....imagine I had 100 people sitting in a room download the app. They then open the app which then all perfectly sync to the server so that they are all now running their individual counters in perfect unison. At that point, they lose internet connectivity (yet, the counter continues to run within the app in their phone.) If the app was programmed to start playing a particular song when the internal app counter reached tick X, all 100 phones would start playing the song at the exact same time (when their counters in unison reached tick X).
Sorry for the long question, but wanted to lay out my issue. Thanks everyone!
I found what was wrong:
So apparently http://www.epochconverter.com/ is makes assumptions of the precision of the input values, and from those assumptions values around 841073068 goes to 1996/1997. I'm not sure what is the assumption that leads to that exact date, but honestly I don't care.
Using the attached debugger I called new Date(System.currentTimeMillis()) and it correctly gave me a 10th Jan-1070 date, meaning the clock is not jumping out of the way like crazy.
Original question:
I'm running a single-board computer with Android for and IoT case (this https://developer.qualcomm.com/hardware/dragonboard-410c). The OS running is the plain vanilla Android supplied by Qualcomm.
Currently I'm testing the reliability of the board to be left executing for long periods at once and I'm seeing some very very weird behavior that I can't find an explanation for.
The board was powered up 10 days ago and it have no access to internet (WiFi is on but no access point setup and no Ethernet). The bluetooth is on and there're iBeacons and Eddystone in the office. Also there are WiFi in the area.
If I go now to Settings -> Date and Time, or check the notification shade or enter the clock app, or the calendar app, I see 10th of January 1970. Which is expected and basically showing for how long the board been running.
The app on it have an always running service, which does some data processing and some disk-logging (for debugging).
From the logs, I can see that System.currentTimeMillis() was returning an expected value when the board was initially powered on. That means, the beginning of the logs indicate an epoch time in January 1970.
But at the end of the logs (and also attaching the debugger on the live process), the value of System.currentTimeMillis() is somewhere in Sep/Oct 1996. Example values: 841073068, 841263234, 841579239
So my question is:
What is happening here?
Why System.currentTimeMillis() value changed and what could have changed it?
Why the Android UI (notification, clock app, settings) still shows me 1970? Where are they getting this value from?
edit:
There's been some confusion on the answers, and I can see my question was lacking the details.
I do not want to measure difference of time. I need an actual time stamp. Those values will be reported with bluetooth LE events via POST to our backend. This "no network" thing is a reliability test that we're running on the board, but we do expect to have network most of the time, and the boards should auto-update their times from network using the normal Android ways.
I'm just trying to understand on the current batch of testing, what went wrong and why.
Well, as you already know, the current system time (System.currentTimeMillis()) can be modified by any process if desired, it's perfectly be possible that it was modified by another process. It's not a reliable method to measure up-time.
I would rater use something like:
SystemClock.uptimeMillis()
Which returns the elapsed time (in milliseconds) since the device booted (not including time spent in deep-sleep).
I would also like to mention that I suspect that Bluetooth has something to do with it, I can imagine that Bluetooth uses the system time for pairing and security just like SSL does (but I'm no expert). GPS could also be a problem as GPS can be used to obtain an UTC time value, but I'm not sure if your board has a GPS module.
Regarding your edit:
Obtaining a valid time-stamp would be quite easy: server time minus the elapsed time reported by your board. But I suggest you either choose to accept the time reported by System.currentTimeMillis() or use the elapsed time instead. At the company I work we also work with embedded Android devices and on our server dashboard we can see both the up-time (up since) and the current device time, but they should not be mixed, at least in my opinion, especially since System.currentTimeMillis() is subject to changes and is affected by summer and winter time.
If you want to measure something, better try System.nanoTime(). Here is difference - https://stackoverflow.com/a/351571/2793494
BACKGROUND:I'm in the process of writing a tasker application that tracks usage of other apps--it keeps track of the time that a reading app is open, for example.
In order to make sure that I'm actually reading and not just leaving the reading app open, I want to make the display timeout 30 seconds long.
ISSUE: The reading app locks the display so it never times out. How can I override the reading app settings to make my 30 second timeout take precedence?
I can't find anything out online because everyone is trying to do the opposite. However, everyone else's Tasker timeout seems to avoid conflicts naturally, so I'm not sure why mine is having issues.
Pseudo code:
Event: Reading app is active AND display is on
Start time = current time
Timeout save = system timeout
Display->display timeout->30 seconds
Event: Reading app closes OR display is off
Total time += current time - start time
Display->display timeout->Timeout save
have you tried with Secure Settings plugin?
it does have better than Tasker control over some of the OS parameters
After extensive research, I have found that there is no way to override the setting. (At least not for the beginners like me)
Google briefly made it possible to override app permissions in Android 4.3, but soon took that privilege away in a subsequent update. Pity.
A cheap and dirty workaround that I came up with is to have a small dialog in a corner with a timer that counts down for your screen timeout. In the last 10 seconds, a button becomes visible which resets the timer and hides the button, or else the display is shut off. (This works for the purposes of MY app -- My intention was to make sure the user was interacting with a third-party reading app, and not just turning it on and walking away, as my app counts the amount of time the reading app is open and the display is on).
#Tomaski - Unfortunately, the Secure Settings plugin doesn't have this power, although you are correct that its capabilities are greater than vanilla Tasker's.
Let me summarize my problem and what I would like to achieve.
I have a SonyEricsson X10i phone with Android 2.3.3. I realized that sometimes my phone not receiving calls even if it indicating full coverage. I checked myself in the MSC/VLR and it indicates that I registered and my phone is currently active (and also there is no IMSI DETACH flag), so it should working correctly (only the last Activate Date is a little bit old ~couple of hours, which can be good as well, without SMS/Call/Location Update), as I mentioned before the phone indicates full coverage and it seems it’s on the network. But when I tried to call it I only reached the Voice Mail.
In the MSC/VLR I see No Paging Response Cause for the call, but the phone does nothing. I tried with other SW version (4.0.3 ICS), but the same result. But I not noticed similar behaviour with a different handset (same type).
Sorry for the long summary.
So because what I described above, I ‘m trying to write an application/service which will perform GSM/UMTS location update in 15-20 minutes, but I couldn’t find any kind of procedure in android.telephony.gsm.GsmCellLocation, android.telephony.TelephonyManager which will do this for me.
My other concern is the
getState()/setStateOutOfService()/ setState() procedures from ServiceState class…
It seems they not really working. For example, when I first call the getState() I always get back STATE_OUT_OF_SERVICE, which is not true…
When I’m set the state to STATE_POWER_OFF or STATE_IN_SERVICE, at least I get back that state from getState() afterwards, but the phone does nothing for that . (Not even indicate out of coverage,etc…)
Every suggestion/comment are welcome.
I have also seen this problem many times (2 phones from the same manufacturer as yours). From your question, I understand that you want to force the phone to send an MM periodic location update (which it should be sending anyway).
This is too low level, and there's nowhere you can force this directly in the programming interface. The mobility management procedure is part of the phone stack, and is specified in detail in 3GPP TS 24.008, available from www.3gpp.org. Paragraph 4.2.2 defines when the phone is supposed to send these location updates.
The only other thing would be to try by indirect means to force the phone into a condition where it would send a location update. You might be able to do that by trying to select another network manually. If it's successful, and you then manually re-select your home network, then you would trigger a location update. If it's rejected and falls back to its home network, then I think a location update would be triggered as well.
But there would also be small costs to this - battery use while it does a networks scan, and time lost while it scans and does manual network selection.
(My personal experience is that the lost calls don't happen often enough to justify this.)
One of the costs on a phone is that of sending messages, like for instance heartbeat messages to a service in order to be able to receive push messages.
One solution I'm trying for is to set up my timers with a time frame, for earliest heartbeat, and latest, so that when I hit the early time, I'll start listening for network traffic, and if the radio on the phone is busy anyway, I'll send my heartbeat when it is.
The idea is that I may save some power by preventing the phone from having to power up the radio just for me.
That is the theory.
But there are two problems. I'm new to Android, and I haven't been able to figure out if there is such a service I can listen to.
I'm aiming at Android 2.1 for the widest possible audience.
What you ask is covered in Android Training:
http://developer.android.com/training/efficient-downloads/regular_updates.html
Other sections about Transferring Data Without Draining the Battery should be helpful, too.