I try to make an app which can assume the sleeping time of the user.
Samsung devices (samsung health) can assume the sleeping period based on yesterday last, and today first interaction. The app no needs to run into background. So I think, that it reads somehow from the relevant device data.
Is there any way to get the time when the user uses his/her phone in Swift?
Related
I am creating an idle game (user is rewarded for offline time with ressources). For that calculation I will need the elapsed time since the app was closed.
My first idea was to save the current time when the app is closed and read the current time when the app is opened. But what if a malicious user changes the system time between those actions? The user could get as many ressources as he wants with this trick.
My solution would be to consult a time server to get its current time when closing and opening the app. But this would mean the app would need to be always online, which I am trying to avoid.
Is there any other way I could use to accomplish this?
I don't think it means that the app always needs to be online. You just take the server time when the user closes the app and you take the time when the user opens the app again. You then subtract the first from the latter and then you have the offline time. Assuming of course that you save the "last_closed" time in a database of some sort.
When you are online you read correct time from an api which shows greenwich time not from user's device; so that you always have correct time.
I have specific requirement where i want to fetch data from the connected Ble Device every 15 mins for a period of time like form 10:00 PM to 10:00 AM. Can it be done when my app is in background and device is locked. Obviously, user won't keep the app in foreground for so long. Any suggestions on how to achieve this.
It may be achieved but unfortunately you need to solve this from device perspective.
Your device will need to wake up and initiate connection with your phone whenever you need to sync data. It will wake up your application and even launch it if it was terminated. You can then initiate a standard background process for which you have limited time to do whatever needs to be done. When complete you should disconnect from your device and wait for the process to be repeated.
There might be some hacks like using silent push notifications to wake up your app and try to connect but Apple will most likely not allow this plus there is a great chance your BT will simply not work in that state. Still it is something to try if you really need it.
You have the problem that you can't have a timer in an iOS app. Therefore you have some options that require specific behaviour of the peripheral.
One option is to let the app first connect, and always upon disconnect, it tries to reconnect. Then simply make the peripheral don't advertise for 15 minutes. As soon as it advertises again your app will be woken up because it connected. You can then fetch your data.
Another option is to be constantly connected and have a timer in the peripheral that notifies data every 15 minutes.
Both options requires you to have background capabilities enabled in your app and State Preservation and Restoration.
In background mode(app was killed) iOS device cant communicate with BLE.
Only scan BLE device which have service uuid.
Only background scanning is possible in iOS.
So u can get notification while peripheral was found in Background mode.
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)
In my application i want to run an internal clock in background mode [while application is not running in foreground].
The whole functionality will be like this:
The objective is to get the server time to use in the application, because using device time may sometimes cause issues. The issues may be in situations like somebody has changed the user's iPhone time etc. So i am following the below method.
-Running an internal clock in my application background even if the application is not running.
-Communicate with server every 15 minutes to get the real time and run a timer.
-If net is disconnected in between,timer will continue and take the timer time.
My application is heavily depended on this time factor as this is a ticket booking system.Kindly help me to implement this or please confirm whether this is possible or not?
I am developing an iPhone application which involves Ticket Booking System. I registered my application as location based beacuse it is using user's location taken in background for a purpose.
My problem is that i need to run an internal clock in my application in background mode. I need to write the codes for internal clock in core location delegate methods, so that internal clock will also run along with the location bsed services. Will my app get rejected? Is anything wrong in doing like this?
I need to get the correct time to use in my app, so that i am running this internal clock. I can use NSDate, but that will return the device time. Anyone can change the device time. So once somebody chaged, wrong time will affect the smooth functioning of the app. Kindly some body suggest to get the correct time with out running the internal clock ?
Update: Sorry to say my original answer isn't correct. When the device goes to sleep (can happen sometime after it's locked) the internal CPU clock stops ticking, and mach_absolute_time won't update either. Theoretically it will return the exact same value if you call it right before the device went to sleep, and after it awakes.
The best available way I know of to check for date changes is kern.boottime, it holds the boot time, and is modified whenever the system time changes. Among other things, kern.boottime will be updated if the user changes the time, or if the OS changes the time itself according to info from cell towers.
So, in your case, you can take the original time you calculated and modify it according to the modifications in kern.boottime. If you see kern.boottime changed significantly, it may mean that the device was turned off, and in this case you will need to contact the server to ask it for the time until the flight.
Relevant code:
time_t getBootTimeSecs(void)
{
struct timeval boottime;
size_t size = sizeof(boottime);
int ret = sysctlbyname("kern.boottime", &boottime, &size, NULL, 0);
assert(ret == 0);
return boottime.tv_sec;
}
Original (incorrect) answer: You can use mach_absolute_time which isn't affected by date changes made by the user.
When you book the ticket, get the correct date from the server and record mach_absolute_time. Now you will always be able to call mach_absolute_time whenever you want, calculate the difference from the one you recorded initially, and display the correct date.
This will only work as long as the device wasn't shut down, in that case it makes sense for the app to re-connect to the server to get the correct date.
You can also either Local or Push Notifications to alert the user when the target date is getting closer, even if the app isn't running.
apple is support small task for background mode which will work for approximate 10 sec only.
so you can do one thing when app is active then get time form server and update your local time according that.
I think that you can only detect that the date of the iOs device has been changed (using NSSystemClockDidChangeNotification).
I guess you to use this notification and force reload the real date of your application from your server (With a WebService).
EDIT: You can use the systemUptime in NSProcessInfo:
NSLog(#"ProcessInfo System uptime: %f",[NSProcessInfo processInfo].systemUptime);
but it will not solve your problem if the Device is restarted.
I think there are 2 ways you can go about solving your problem.
Never use system time. In other words, never call [NSDate date] in your code. When you need the current time, call an NTP server. This will of course cause latency in your app, but will guarantee accuracy.
When the app launches, or enters foreground, verify that the system time is reasonably accurate against an NTP server. If the system time is off by more than your tolerance level, then do not let them continue running the app until they address it. If the system time is okay, then start monitoring to ensure they don't change the system time while running the app (NSSystemClockDidChangeNotification). If they pass the initial check, but the move the clock forward, you can catch that and disable the app til they change it back to being accurate.
Here is an iOS NTP implementation which could be helpful in implementing either solution above. http://code.google.com/p/ios-ntp/
EDIT: The Ticketmaster app uses technique #2, so this seems like a reasonable solution for a ticketing app that requires your system time to be correct.
timezone settings should not affect time as in UTC
your app cannot run in the background. Abusing the location requirement for this will cause your app to be rejected by Apple
so my suggestion: do the logic server side with push notification
I have an app that requires me to take an action after some period of time. For example, if an user hasn't been inside the app in few weeks, when the user eventually starts the app, I have to ask them to put in a special code that was given to them when they installed this app. (this is an in-house app and i am being required to do this due to security concerns)
I am using the [NSDate date] method to retrieve the date when the user logs in and save it into a database. I compare this saved date next time they open up the app and see how long its been since their last login. The problem is that [NSDate date] gives the time that is effected by the time settings that can be changed manually by the user in the native settings app. As you can probably tell, this causes lots of problems to my situation. If the user is suppose to be put the special code after 3 weeks of inactivity, he can cause the app to show this screen by modifying the time in the native settings app or worse, get away from it by setting the time to a previous date that will be within 3 weeks of his activity.
Is there a way to get the "system time" instead of the "user time"? I have looked into mach_absolute_time() but this gets reset after restart of the device. Since the time of inactivity I will be comparing against is pretty large, chances are device would have been restarted by then. I also thought of using network connection to get the time from servers outside the app, but lots of users won't have access to wifi where they use their iPads. That will be my last resort solution if i can't find anything else. Because of their location during usage, I am trying to use everything on the device itself.
Am I overlooking something simple here? this seems too simple of a problem to not have an answer. Please guide me toward the right direction. Thank you in advance.
Why not query a remote server for the time - lots of NTP servers about or just make a simple HTTP request to a php script on your own server. Of course if your app is likely never to be connected to the internet that could be a problem, but once you have a 3rd party time its quite easy to guess if the user has been playing with the clock.
If this is an inhouse app (so you aren't constrained by Apples approval process), you could mark your app as doing some background stuff (voip or receiving location updates), so that the app will always be active and you'd be able to update some sort of an "unused" counter. Voip app will even be restarted by the OS after device reboot.
But of course it'll drain the battery somewhat.
Either: make having the actual time an essential feature of your app. This way the users will have a need to keep the time of the device current and can't go back three weeks
Or: mark the code as expired and save this information before the app informs the user. This will stop most user from setting the time back. Most will try once or twice, see that the app stays disabled and will give up.
You can also save the timestamp of the last successful execution and if that is more than a reasonable time frame in the future (remember summer/winter time) then consider it a "hack attempt". Put a CRC check (or whatever obscure idea you come up with) on that timestamp and save it too and you will stop a large number of script kiddies.
You can never stop the diehard hacker who search actively for every trick you might have put into the app. Just focus on the "average" user.