On a jailbroken iOS device, something like this is possible with a launch daemon, assuming the device is not locked/put to sleep. (It may also be possible if the device is locked, but I'm not sure how to do it.)
I'll give a brief sketch of the steps; let me know if you need more detail.
First of all, create a launch daemon. You don't want to use UIApplication
for a launch daemon, so you should create a custom main()
function. To make it always be running in the background, you need to add a plist file to /Library/LaunchDaemons
, named something like com.yourcompany.yourdaemonname
.
Putting the following keys in should make it work:
<key>Label</key>
<string>com.yourcompany.yourdaemonname</string>
<key>MachServices</key>
<dict>
<key>com.yourcompany.yourdaemonname</key>
<true/>
</dict>
<key>ProgramArguments</key>
<array>
<string>/path/to/daemon/executable</string>
</array>
<key>UserName</key>
<string>mobile</string>
<key>OnDemand</key>
<false/>
<key>StandardErrorPath</key>
<string>/dev/null</string>
<key>Disabled</key>
<false/>
You may also need to call launchctl load /Library/LaunchDaemons/com.yourcompany.yourdaemonname.plist
after you install the daemon if you don't restart the phone (and launchctl unload
before you reinstall it if you update). I'm not entirely sure.
Once you have your daemon running, you can have it act periodically by scheduling an NSTimer
. I'm not sure if there's a way to check how long the phone has been idle for, but it might be possible. Once you resolve that issue, though, you can start an application (your main UI application) using the following code:
#import <dlfcn.h>
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
...
void* sbServices = dlopen(SBSERVPATH, RTLD_LAZY);
int (*SBSLaunchApplicationWithIdentifier)(CFStringRef identifier, Boolean suspended) = dlsym(sbServices, "SBSLaunchApplicationWithIdentifier");
int result;
result = SBSLaunchApplicationWithIdentifier(CFSTR("com.yourcompany.youruiapp"), false);
dlclose(sbServices);