Is it possible to use an NSTimer to wake a jailbroken iPhone from deep sleep?

后端 未结 2 1663
盖世英雄少女心
盖世英雄少女心 2021-01-06 08:54

Note: further down in the edits there\'s simple code that generates the problem without the full complexity of my original program.

I\'m trying to code an alarm-cloc

2条回答
  •  庸人自扰
    2021-01-06 09:30

    I've worked out a method that works for me. As per my long exchange with Nate (and I definitely wouldn't have been able to work out what was going on without his help), this seems to happen automatically on some systems, but not on others. The problem on my phone seemed to be that powerd was putting the phone into some sort of deep sleep that paused the NSTimers and didn't allow them to fire properly.

    Rather than disabling deep sleep (which I suspect has negative power implications) I scheduled a power event:

    NSDate *wakeTime = [[NSDate date] dateByAddingTimeInterval:(delayInSeconds - 10)];
    int reply = IOPMSchedulePowerEvent((CFDateRef)wakeTime, CFSTR("com.amm.daemontimertest"), CFSTR(kIOPMAutoWake));
    

    This successfully wakes the phone 10 seconds before the alarm is supposed to go off. (The interval isn't precise. I wanted it to be short enough that the phone wouldn't go back to sleep, but long enough that if the phone takes a moment to wake up the timer can still go at the right time. I'll probably shorten it to just 3 or 4 seconds.

    The remaining problem is that the NSTimer for the alarm itself won't update automatically, and so it'll be late by whatever period the phone was asleep for. To fix this you can cancel and reschedule the NSTimer whenever the phone wakes up. I did this by registering for a notification that the power management system posts whenever the power state changes:

    int status, notifyToken;
    status = notify_register_dispatch("com.apple.powermanagement.systempowerstate",
                                      ¬ifyToken,
                                      dispatch_get_main_queue(), ^(int t) {
                                          // do stuff to cancel currently running timer and schedule a new one here
                                      });
    

    The inefficiency here is that the notification is posted both on sleeps and wakes, but I haven't been able to find an alternative yet.

    I hope this is helpful to anyone else who was struggling with this issue.

提交回复
热议问题