慕尼黑的夜晚无繁华
我也见过这种行为。经过多次尝试,我发现了两件事情,这可能会有所帮助。但我仍不清楚这会如何影响检讨过程。如果您使用其中一个后台功能,应用程序将由iOS在后台再次启动,一旦退出(由系统)。我们稍后会滥用这个。在我的例子中,我使用了在我的plist中启用的VoIP回退。这里的所有代码都是在AppDelegate中完成的:// if the iOS device allows background execution,// this Handler will be called- (void)backgroundHandler {
NSLog(@"### -->VOIP backgrounding callback");
// try to do sth. According to Apple we have ONLY 30 seconds to perform this Task!
// Else the Application will be terminated!
UIApplication* app = [UIApplication sharedApplication];
NSArray* oldNotifications = [app scheduledLocalNotifications];
// Clear out the old notification before scheduling a new one.
if ([oldNotifications count] > 0) [app cancelAllLocalNotifications];
// Create a new notification
UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
if (alarm)
{
alarm.fireDate = [NSDate date];
alarm.timeZone = [NSTimeZone defaultTimeZone];
alarm.repeatInterval = 0;
alarm.soundName = @"alarmsound.caf";
alarm.alertBody = @"Don't Panic! This is just a Push-Notification Test.";
[app scheduleLocalNotification:alarm];
}}注册是在- (void)applicationDidEnterBackground:(UIApplication *)application {
// This is where you can do your X Minutes, if >= 10Minutes is okay.
BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
if (backgroundAccepted)
{
NSLog(@"VOIP backgrounding accepted");
}}现在神奇的事情发生了:我甚至不使用VoIP-Socket。但是这10分钟的回调提供了一个很好的副作用:在10分钟(有时更早)之后,我发现我的计时器和以前的运行记录被执行了一段时间。你可以看到这个,如果你放置一些NSlog(.)进入你的密码。这意味着,这个简短的“唤醒”会执行一段时间的代码。根据苹果的说法,我们还有30秒的执行时间。我想,类似线程的背景代码正在执行将近30秒。这是有用的代码,如果你必须“有时”检查一些东西。医生说,所有的背景任务(VoIP,音频,位置更新)将在后台自动重新启动,如果应用程序被终止。VoIP应用程序将在启动后在后台自动启动!通过滥用这种行为,您可以使您的应用程序看起来像运行“永远”。为一个背景进程(即VoIP)注册。这将导致您的应用程序在终止后重新启动。现在编写一些“任务必须完成”的代码。根据苹果的说法,你有一些时间(5秒?)左转完成任务。我发现,这一定是CPU时间。这意味着:如果你什么也不做,你的应用程序还在被执行!苹果建议,如果你的工作完成了,就打电话给一个呼气处理程序。在下面的代码中,您可以看到,我在期满处理程序上有一个注释。这将导致您的应用程序运行,只要系统允许您的应用程序运行。所有计时器和线程都在运行,直到iOS终止应用程序为止。- (void)applicationDidEnterBackground:(UIApplication *)application {
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// you can do sth. here, or simply do nothing!
// All your background treads and timers are still being executed
while (background)
[self doSomething];
// This is where you can do your "X minutes" in seconds (here 10)
sleep(10);
}
// And never call the expirationHandler, so your App runs
// until the system terminates our process
//[app endBackgroundTask:bgTask];
//bgTask = UIBackgroundTaskInvalid;
}); }在这里非常空闲的CPU时间,你的应用程序运行时间更长!但有一点是肯定的:你的应用程序会在一段时间后被终止。但是因为你注册了你的应用程序为VoIP或其他的一个,系统在后台重新启动应用程序,这将重新启动你的后台进程;-)用这个乒乓,我可以做很多回植。但请记住,与CPU的时间是非常空闲的。并保存所有数据,以恢复您的视图-您的应用程序将在一段时间后终止。为了使它看起来仍在运行,您必须在醒来后跳回最后的“状态”。我不知道这是不是你之前提到的应用程序的方法,但它对我有用。希望我能帮上忙最新情况:在测量了BG任务的时间之后,出现了一个惊喜。BG任务以600秒为限。这是VoIP最短时间的最小时间(setKeepAliveTimeout:600)。因此,这段代码在后台导致“无限”执行:标题:UIBackgroundTaskIdentifier bgTask;代码:// if the iOS device allows background execution,// this Handler will be called- (void)backgroundHandler {
NSLog(@"### -->VOIP backgrounding callback");
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (1) {
NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self doSomething];
sleep(1);
} }); - (void)applicationDidEnterBackground:(UIApplication *)application {
BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
if (backgroundAccepted)
{
NSLog(@"VOIP backgrounding accepted");
}
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (1) {
NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self doSomething];
sleep(1);
}
}); }在应用程序超时后,将调用VoIP期满处理程序,您只需重新启动一个长时间运行的任务。此任务将在600秒后终止。但是会再次调用过期处理程序,这将启动另一个长时间运行的任务,等等。现在您只需检查应用程序是否返回到前台。然后关闭bgTask,你就完成了。也许一个人能做某事。在长时间运行的任务中,呼气处理程序就像这样。试试看。用你的控制台,看看会发生什么.玩得开心!更新2:有时候简化一些事情会有帮助。我的新方法是:- (void)applicationDidEnterBackground:(UIApplication *)application {
UIApplication* app = [UIApplication sharedApplication];
// it's better to move "dispatch_block_t expirationHandler"
// into your headerfile and initialize the code somewhere else
// i.e.
// - (void)applicationDidFinishLaunching:(UIApplication *)application {//// expirationHandler = ^{ ... } }
// because your app may crash if you initialize expirationHandler twice.
dispatch_block_t expirationHandler;
expirationHandler = ^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
};
bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// inform others to stop tasks, if you like
[[NSNotificationCenter defaultCenter] postNotificationName:@"MyApplicationEntersBackground" object:self];
// do your background work here
}); }这起作用了无网络电话攻击。根据文档,如果执行时间结束,过期处理程序(在本例中是我的“期满处理程序”块)将被执行。通过将块定义为块变量,可以在过期处理程序中递归地再次启动长时间运行的任务。这也导致了无止境的处决。如果应用程序再次进入前台,请注意终止任务。如果你不再需要的话就终止任务。根据我自己的经验,我测量了一些东西。使用位置回叫与有全球定位系统收音机是吸吮我的电池非常快。使用我在更新2几乎不需要任何能量。根据“用户体验”,这是一种更好的方法。也许其他的应用程序就是这样工作的,把它的行为隐藏在GPS功能后面.