繁体   English   中英

自上次应用程序启动以来,如何检测iphone是否已重新启动

[英]How can I detect whether the iphone has been rebooted since last time app started

我想从我的应用程序中检测到自上次我的应用程序启动以来iPhone是否已重新启动。 我需要这样做,因为我的应用程序使用自上次系统重启后的计时器计时用户的时间,我想检测重启,以便我可以使时间无效。

有没有我可以从系统控制台日志中提取信息,如重启,崩溃? xcode中的组织者可以访问它,也许我也可以访问它。

如果没有,您能想到其他获取此信息的方法吗?

这似乎可行:

  • 得到自上次重启以来的时间,对于这个例子,让我们把它存储在一个名为'tslr'的变量中(我猜想持续时间以毫秒为单位,BTW,你怎么做到的?)
  • 获取当前时间,例如将其存储在变量'ct'中
  • 计算最后一次重启时间(我们称之为'lr'),我们有:lr = ct - tslr
  • 商店'lr'

下次启动应用程序时,加载“lr”的先前值,计算新值,如果它们不同,则检测到重新启动(您可能必须容忍一小段差别......也许几毫秒)。

我认为愚弄这一点非常困难......用户必须非常精确地篡改他们的手机时间,并且他们必须在非常精确的时刻启动你的应用程序,正好在新的'lr'时与前一个相同......很难做到,我认为他们能够做到这一点的概率非常接近0。 你不需要任何互联网连接来做到这一点......

在以下情况下,新的'lr'将与前一个相同:

  • 手机没有重启,时间没有改变
  • 时间被篡改,并且用户设法以精确的毫秒启动你的应用程序以欺骗你的算法(这种情况发生的可能性超过了超级)

佐兰的答案是正确的方法; 它是没有网络连接的最接近的。 (出于安全原因,无法访问蜂窝子系统和syslog)

如果您希望防止恶意用户生成虚假时间数据,请让一些中央服务器(或企业部署的可信本地服务器)跟踪与时间相关的事件。

    // Returns true if device has rebooted since last time
    private func deviceRebootedSinceLastTime() -> Bool {
        let userDefaults = NSUserDefaults.standardUserDefaults()
        let systemUptime = NSProcessInfo.processInfo().systemUptime;
        let timeNow = NSDate().timeIntervalSince1970
        let dateOfLastReboot = NSDate(timeIntervalSince1970: timeNow-systemUptime)

        var didDeviceRebootSinceLastTime = false

        if let storedDateOfLastReboot:NSDate = userDefaults.objectForKey("deviceLastRebootDate") as? NSDate {

            if Int(dateOfLastReboot.timeIntervalSinceDate(storedDateOfLastReboot)) < 1 { //
                print("Reboot time didn't change - date: \(dateOfLastReboot)");
            }
            else {
                print("Reboot time has changed - from: \(storedDateOfLastReboot) to \(dateOfLastReboot)");
                didDeviceRebootSinceLastTime = true

            }
        }
        else {
            print("Reboot time is saved for the first time")
            didDeviceRebootSinceLastTime = true // first time we save value
        }

        userDefaults.setObject(dateOfLastReboot, forKey: "deviceLastRebootDate")
        userDefaults.synchronize() // don't forget this!!!

        return didDeviceRebootSinceLastTime;
    }

从iPhone或NIST获取并保存时间,从BSD正常运行时间函数获取当前运行时间。 对于NIST时间,请参阅如何在iPhone中获取实时,而不是用户在“设置”中设置的时间?

如果要检查重新启动,请获取这些值的新值,计算每个值的经过时间并比较经过的时间。 根据差异,您应该能够确定重新启动。

这是我制作的。 它需要GMT中的当前时间和自上次重新引导以来的时间来推断设备上次重新启动的日期。 然后,它使用NSUserDefaults在内存中跟踪此日期。 请享用!

注:由于要检查这一点,因为最后一次的应用程序已经开始 ,你需要确保你调用的方法随时应用程序已启动。 最简单的方法是在+(void)initialize {以及随后在需要手动检查时调用下面的方法

#define nowInSeconds CFAbsoluteTimeGetCurrent()//since Jan 1 2001 00:00:00 GMT
#define secondsSinceDeviceRestart ((int)round([[NSProcessInfo processInfo] systemUptime]))
#define storage [NSUserDefaults standardUserDefaults]
#define DISTANCE(__valueOne, __valueTwo) ((((__valueOne)-(__valueTwo))>=0)?((__valueOne)-(__valueTwo)):((__valueTwo)-(__valueOne)))

+(BOOL)didDeviceReset {
    static BOOL didDeviceReset;
    static dispatch_once_t onceToken;
    int currentRestartDate = nowInSeconds-secondsSinceDeviceRestart;
    int previousRestartDate = (int)[((NSNumber *)[storage objectForKey:@"previousRestartDate"]) integerValue];
    int dateVarianceThreshold = 10;
    dispatch_once(&onceToken, ^{
        if (!previousRestartDate || DISTANCE(currentRestartDate, previousRestartDate) > dateVarianceThreshold) {
            didDeviceReset = YES;
        } else {
            didDeviceReset = NO;
        }
    });
    [storage setObject:@(currentRestartDate) forKey:@"previousRestartDate"];
    [storage synchronize];
    return didDeviceReset;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM