In iOS, using Swift, how do you get the time of iPhone boot? - ios

In core motion, data is returned in a class inheriting from CMLogItem, which has a timestamp property. The timestamp is a TimeInterval that is the time since the device booted.
How do I get when the device booted?

From the comments, I was able to find ProcessInfo.processInfo.systemUptime which is the time since last boot. From this, and Date(), I can get the time of start via:
time_of_last_boot = Date() - ProcessInfo.processInfo.systemUptime

Related

iOS: OperationQueue.schedule(after: Date) that cannot be triggered by date change

Problem
I need to get a callback when at least X amount of time has passed since the date for the callback has been set.
Example 1:
This would have worked great, but it's possible to trigger an execution of the block by setting the date earlier than the correct time right now:
let responseDate = Date().advanced(by: 60) // 1 min
OperationQueue.current.schedule(after: .init(responseDate), {
print("the time is now!") // possible to set the current date 1 min before
}
On the other hand, the solution for getting a current uptime from this answer works great, but it requires timer constantly running to check if we're close to date.
Is it possible to combine these two approaches and somehow "attach" a callback to KERN_BOOTTIME, so that the OS will call my method when the boottime reaches a certain value?
I'm looking as well to alternative engineering solutions that satisfy two criterias:
It should not be possible to trigger the callback by resetting the device date to some arbitrary value in the past
If the device has been put to sleep (e.g. by pressing the on/off side button), the clock should still be "ticking", so that the method will be called back while the app is running in the background.
More details:
Backgrounding / app termination is out of scope
The main point is to prevent a bypass by switching the date backwards in the settings.

Why is my user still able to manipulate the app's time when I'm fetching the time from a server?

I'm trying to fetch the time of my app from the firebase servers using FirebaseFirestore.Timestamp() so that my users are unable to change the device time and fool the app into giving out daily credits sooner than they should get them.
To that end, I have used the following code, but this still returns the time on the device itself.
What I want to achieve is that whenever a button is pressed, getTime() gets called and prints the time as per the Firestore server, and not as per the device on which the app is installed.
My code is as below:
func getTime() {
let time = FirebaseFirestore.Timestamp()
print(time)
// Prints <FIRTimestamp: seconds=1586518212 nanoseconds=6677150>
let RequestedDate = time.dateValue()
print("\(RequestedDate) CHECKHERE")
// Prints 2020-04-10 11:30:12 +0000 CHECKHERE, which is the wrong date I set using the device itself.
let calendar = Calendar.current
let componentsss = calendar.dateComponents([.day, .hour], from: RequestedDate)
print(componentsss)
// Prints the components of the device time.
}

Get phone (GSM) signal strength without use of private API

I am developing an iOS app in swift and need to know the GSM signal strength. I am aware that this can be done with private API's like CoreTelephony's CTGetSignalStrength, but as my app has to go in the app store, I can't use private API's.
Does any one know of a way to check the signal strength without the use of private API's?
Just a quick idea if you are worried about data transfer speed via cellular. Place some file on server (can be image) and download it. Measure time before and after it has been downloaded. Can repeat. If you know the download time for good connection, you can decide what time is not ok.
You can also request something from server few times to get headers back and thus determine something similar to ping in miliseconds.
func evaluateDownloadTime() -> Double
{
let start = NSDate(); // Start time
// Your Download process to measure
let end = NSDate(); // End time
let timeInterval: Double = end.timeIntervalSinceDate(start);
// Difference in seconds (double). You may need miliseconds.
return timeInterval
}
print("Time measured: \(evaluateTime()) seconds");

iOS-ntp returning same value as device

I'm using the iOS-ntp framework and I'm getting a weird behavior that I cannot understand.
Currently its 13:14 but I changed the time on the device to 13:34 when I make the folioing calls:
NSDate *deviceDate = [NSDate date];
[NetworkClock sharedNetworkClock];
NSDate *networkDate = [NSDate networkDate];
NSLog(#"deviceDate =%#", deviceDate);
NSLog(#"networkDate =%#", networkDate);
What I get is:
deviceDate =2014-05-13 13:34:37
networkDate =2014-05-13 13:34:38
Obviously I expected:
deviceDate =2014-05-13 13:34:37
networkDate =2014-05-13 13:14:38
How am I getting the same date value?
Thanks in advance.
EDIT:
Snooping the connection I intercepted this packet from the server to the app:
Network Time Protocol (NTP Version 3, server)
Reference ID: 212.82.32.15
Reference Timestamp: May 16, 2014 14:56:40.999638000 UTC
Origin Timestamp: May 16, 2014 18:25:02.688373000 UTC
Receive Timestamp: May 16, 2014 15:15:14.862829000 UTC
Transmit Timestamp: May 16, 2014 15:15:14.862889000 UTC
After this the framework call returns 18:25
Edit It turns out that the lack of the config file was not the problem in this case. Please read further.
There is logic in the algorithm to decide that certain time stamps are invalid; this is used to determine if the time can be trusted. This decision is made by determining if the server clock was set less than 1 hour ago. It uses your current time as the reference point.
When I skew my clock forward by a couple of hours (and I'm currently in UTC+1 (Summer Time)), I never get a sync, because this time will always be out by at least a few hours, i.e. the test for this will never get a good value.
If you comment out the check that:
(-[[self dateFromNetworkTime:&ntpServerBaseTime] timeIntervalSinceNow] < 3600.0)
in the evaluatePacket method NetAssociation.m, you avoid this check, and can get a wider degree of offsets. I've linked a github reference to the patch that accomplishes this in relation to the master.
Being unable to sync with NTP once your clock is significantly out of whack is what can be considered a safety feature, but because we're just using it to calculate the delta between the system clock and the network clock, it doesn't actually give us anything in this case
It's relatively poorly documented in the framework, but you need to copy the ntp.hosts file from the framework resources directory into the project that uses the framework, and ensure that the file is copied as part of the Copy Bundle Resources part of the app's Build Phases.
If you don't copy the file, the framework has no time references to use and so never determines the offset to use, resulting in the OS time at all times.
The cocoapods version of the framework doesn't use this configuration file, and instead has the method networkDateWithServer:(NSString *)server, which allows you to explicitly specify the NTP server to use.
The framework could probably react in a more appropriate manner (e.g. logging the lack of the file) rather than just carrying on, but that's a design decision.

Have the current server time locally in the app.

I'm building an app that is using a lot of NSDate class. But NSDate uses the time from the device, so if the user changes the hour in it's device the app is going to have a fake time/date and the app is not going to be synced with the server and the user experience is going to be bad...
So I need somehow to get all the dates relative to the server, I can request the time to the server each time I do a [[NSDate alloc] init]because I'm using that A LOT... so I need a way to always get the date relative to the server... something like [[MYDate alloc] init] and having my server time there...
The best solution I could think off so far is: When the app starts I ask the server it's current unix time, after having that response I set inside a singleton a selector running once per second updating this unix time and I change every call to [[NSDate alloc] init] with my own Singleton class that keeps my server time updated... What I'm not sure how to handle is when the app goes to background... my time is not going to be synced...
What do you guys think about this??
Thanks!!
This can be easily accomplished by using an NSDate subclass.
e.g.
#interface MyDate : NSDate{
}
#end
#implementation MyDate
- (id) init{
if(![super initWithTimeIntervalSince1970:[ServerSingleton time]])
return nil;
return self;
}
#end
That should do what you are asking. As for the singleton, you don't need to check every second, that is a lot of work for the iOS device, the network, and your server. Instead, you only need to check the server once, at the start of your app. Then, have your singleton look something like this:
- (void)checkTime{
self.timeOffset = serverTime - deviceTime;
}
- (time_t)time{
return deviceTime - self.timeOffset;
}
That should only require checking once, to get the current difference in time between the device and the server. Then, you just subtract the time offset from the current device time to get the current time on the server.

Resources