How to synchronize an audio on 2 or more ios devices - iphone

I have to perform an action (play song at a time on multiple devices without lag) at a given point of time. My requirement is that the app should not use any internet connection. So I need an exact point of time when to play data(Audio)]
I have already tried following:
Play song after 5 seconds on all devices. (still causes lag of milliseconds)
Send a small text notification to identify playing of the song and then start playing on all devices. But sending and receiving this notification takes time of milliseconds :(:(
Set time to automatic on all devices and then checked time difference of text message passing, It has milliseconds gap in each testing.

First you need to synchronize the 2 devices internal time.
Apparently the most accurate clock you can have on iOS is the absolute time by doing :
CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
Then you need to send this time from device A to device B retrieve the difference on device B and send it back to A , then compare the difference with the time spent in the network transaction. In this way you can have a quite accurate synchronisation of the 2 devices time. (This is presuming the network time is symmetric between request and response and that there is not much overhead on your calculation on device B).
From there you can easily instantiate 2 AVAudioPlayer on the devices set the song and call prepareToPlay and finally fire the play method according to the delay on the synch.
This should give you a not noticeable precision.
Another route you can take is the one of placing an AudioUnit on the second device connected to the microphone in order to sync the music accordingly to the first device emitted sound.

Known Issue
When sleeping or waiting for extremely precise time intervals, timers may be delayed by up to 1 millisecond.
For reference :
https://developer.apple.com/library/ios/releasenotes/General/RN-iOSSDK-7.0/

Related

flutter check stream for new items

TL;DR at the end
I am building an app to read data from color measuring devices via bluetooth.
Maybe, in the future, the app wil replace the very expensive OLED displays, and measurements will only be triggered from the app. However, now, in the transitioning phase, measurements can be triggered both from the app and the colorimeter. This raises the problem of getting the data on the device running the app, no matter where the measurement is triggered. The bluetooth input is handled as a stream.
How can i run a small service in the background that checks the stream for a new (specific) input without discarding other inputs? And would this cost less battery than polling the colorimeter like once every two seconds?
TL;DR:
How do I constantly check a Stream for new items, while reomving only items from the stream that fit certain conditions?
How do I implement such a solution into my app?
Is this more battery efficient than polling the device status every two seconds?
Since your data comes via a Stream you should take a look at StreamBuilder https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html Here you can find a video on it and some example code fo you to use.

Measuring heartrate while Apple Watch is in sleep mode [duplicate]

I need to make an app that records heart rate data in near real time and send this data to a server as soon as possible.
First I took this approach: Watch os 2.0 beta: access heart beat rate
In fact it is working fine. There is new heart rate data in the HealthKit every five seconds. But now I have the problem that I can't sync that with a server.
My first approach was the Watch app. The watch was sending data to a server. That doesn't work because as soon as the screen turns black on the watch, it stops sending.
My next approach was to query the HealthKit on the iPhone every five seconds for new data. This works, as long as the app is in foreground.
Then I saw that there's some kind of background functionality that watches the HealthKit itself and revokes the app from background and you can do something.(enableBackgroundDeliveryForType) This doesn't seem to work for heart rate (the Apple Documentation says for things like steps this doesn't work, I guess heart rate is one of those).
I'm stuck now. Do you know how to it? I would need some background task that is executed every 5-10 seconds on the iPhone. That seems to be impossible
UPDATE
As noticed by #BootMaker, Apple made background mode available for HKWorkout apps in WatchOS 3, so it's working now. You have to run a HKWorkoutSession and this will keep your heartrate delivery in real time even when the app is in the background (dark screen on watch)
The closest you are going to be is while the watch app is open.
Why I'm stating this?
There are two HealthKit's Database (one at the iPhone and another at the Apple Watch). When they sync is arbitrary and decided only by the O.S.
The closest you are going to be to real time is when you don't have any password locking your screen in iPhone or Apple Watch.
Either way, there's no guarantee that the sync will happen every time a new measure is added to Apple Watch's HealthKit
The only way to force the Heart rate sensor into working in real time is via workouts or observer while your Apple Watch app is in FOREGROUND.
Background delivery is NOT available for Apple Watch apps.
Watch OS 2 request the sensor to measure automatically (in background) every 10 minutes minimum.
There's no other workaround, if you need real time for longer periods, or while the user is not using your app, you will need to use an specialized wearable.
If anyone still need to get heart rate or other data in real time. Use this solution:
Develop an apple watch app/extention
In watch app, using HKHealthStore, HKWorkoutConfiguration, HKWorkoutSession, HKLiveWorkoutBuilder to create an Workout. After create workout, your watch app will get heart rate in real time.
Using watch kit connection with WCSession to send data to iPhone app.
Enable background mode both in apple watch and iPhone.
I tested, even app terminated, we can still get heart rate (I used Local notification for posting heart rate data for debugging)

Calculating time interval in iOS application

I am developing an iOS application for iPod Touch in which my application displays the server time always. I always sync the application time with server time whenever the application comes to foreground by making a web service call to the server. If there is a connectivity loss between my server and client for few hours I wont be able to sync the application time. I read iOS does not support running a timer when the application is in background other than few limited cases mentioned below:
Apps that play audible content to the user while in the background, such as a music player app
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Newsstand apps that need to download and process new content
Apps that receive regular updates from external accessories
So how can I keep track of application time? Whenever the user switches to my application he needs to look at the server time so I need to run a timer to update the last synced server time.
A combination of other answers, create a class in charge of obtaining the server time and maintaining the last time the application was synced to the server using a combination of NSDate* lastSync and applicationDidBecomeActive. For example:
-(void)applicationDidBecomeActive:(UIApplication*)application {
[ServerTimeSync sharedInstance] resync];
}
ServerTimeSync will maintain an NSDate* property with the last sync time (you'll want to convert what the server gives you to an NSDate*).
You can store the NSDate when the app goes into the background. When it resumes, get the current NSDate again, and add the difference to your stored server time.
You don't need a timer for this at all.
I would suggest that when you sync time with your server, you have it return its current UNIX timestamp. You can then do:
[[NSDate date] timeIntervalSince1970];
...to get the device's current UNIX timestamp. Then what you can do is store the difference between these two timestamps. This is the clock skew between the server time and the device time.
You can now compute the server's approximate time by taking the device's current UNIX timestamp and adding the clock skew to it. Adjust for time-zone when displaying it (if you want), and you're done. Whenever you sync time with the server, you can just refresh the stored clock skew value.
If you want to get fancy, you can also attempt to measure and take network latency into account when determining the clock skew.
This approach should work much better than trying to store the server's absolute timestamp and then track how much time has elapsed using a timer (or any other mechanism).

iPhone - Synchronize two iPhones to make them start task on same time

I need to make an application that will start playing same media on two (or more) iPhones simultaneously, the problem is that it has to be perfect, no second delays and such. Is it possible that iPhone has some universal time stamp that is perfectly (or near-perfect) on every device. Or maybe I have some other options?
2 rules:
Find a way to have the same time on each devices
Use a "startAtTime" function using this shared uniform time. No "startNow" function.
the iPhones are supposed to be able to sync their date and time using a remote server, if this is not accurate enough (who knows), a way to achieve this (assuming you iPhone are able to communicate between them already):
The master send its time to a slave 10 (or more) times.
Each time the slave compare it's time with the one received and make a delta
After 10 tries, make a mean of the deltas and use this mean to adjust the slave time accordingly
There's no internal clock that is different to the system clock - so this means that each of the devices could have completely different time settings (in fact, it's highly likely that they will have different time settings even if only by a second or two).
Using a network/internet connection to synchronise against a central time server may be an approach that could be taken, but that would then require the network/internet connection and you would have to set the clocks taking into account lags on the connection to/from the time server.
You could have to have some kind of local synchronising system. If they are in close proximity, one approach may be to create an ad-hoc bluetooth connection between the devices in your app and then use some synchronisation code in you app to get the internal timers the same. You could, for example, have the first app to launch be the "controller" and then all the other apps would seek this controller and synchronise against it. The synchronisation could just be the controller sending out timestamp messages which the other devices can get and set an internal counter to match.
Without knowing much more about the requirements, it's hard to say how best to approach this as there may be limitations regarding time between running the app and it making the sound, or if you have to have a triggering signal, or if it is just at time x they need to make the sound.
If they are in same time zone and same time set ,you can schedule it to start your function in the paticular point of time using NSTimer's
- (id)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;.
One option you have is to access the time from a common server and then start a timer on both devices accordingly (calculating depending on the time you got from the service)so you have exact time on both the devices and then play it ...
Even this has a catch as internet speed may vary and there might be a slight in delay on one of the two devices in getting the response from the server as compared to the other device and looking at your requirement they might go out of sync by a milisecond or so which will be visible.. :/ any other ideas anyone.. ?

Timer running while on home screen iPhone - Objective C

I am interested in building a Timer Based game such as mafia wars or soemthing like that. I'm stuck on one question.
What would be the best way to retain a timer, even if the app is closed?
Should I do this based on the Device Clock? or should I set a time to a server, and get the time when the device starts up?
If any one knows a better way for this,
let me know.
Thanks.
#lessfame
I'll interpret your question as "What's the best way to measure elapsed time between app launches?" instead of "How do I make a timer fire when my app is closed?".
There's no reliable and accurate way to measure time when the device is powered off (remote servers might not be reachable, astronomical measurements might not be possible if it's cloudy, ...). Don't bother.
That said, most CF/NS APIs use CFAbsoluteTime/NSDate (namely, CFRunLoopTimerGetNextFireDate() and -[NSTimer fireDate]). I'm not sure what they do if the system clock changes.
You can use mach_absolute_time() (and it's used internally by some things), but that's just system uptime, so it fails if the phone reboots. I'm not sure if you can get the boot UUID in order to find out if the phone has rebooted.
At the end of the day, CFAbsoluteTimeGetCurrent() or (equivalently) [NSDate date] is probably enough; just make sure that your app behaves sensibly if the time suddenly changes by a day or two in either direction.
Yes, the user can game the system by setting the system clock. You can mitigate this to some extent by occasionally syncing with the server, and keeping track of game time elapsed between syncs. If the difference between elapsed game time and server time is small, then just speed up or slow down the game appropriately to bring elapsed "game time" to real time. If the change is large, you can restore from the last save point on the server, or make the user wait until the elapsed game time has elapsed in server time, or a bunch of other things. This means you can't start playing until the initial sync, but the user has to be online to download the app anyway, so it's not a major problem.
If you only need to retain the time and show how much time elapsed since the game was closed (i.e. you don't need to notify the user when the time is up), you can use the [NSDate timeIntervalSinceNow] method to determine the amount of milliseconds that passed between two times.
If you are saying you want to just know time elapsed since some event, all you do is log the initial time, and then log the final time and compare the difference.
If you need a countdown timer to some event then what you do is set up a local push notification set to go off at the end time.