gpt4 book ai didi

iPhone - 后台轮询事件

转载 作者:行者123 更新时间:2023-12-03 18:09:22 25 4
gpt4 key购买 nike

很长一段时间以来,我一直在我的 iPhone 应用程序中寻找一种每 X 分钟轮询一次以检查数据计数器的方法。在大量阅读后台执行文档和一些试用应用程序后,我认为这在不滥用后台 API 的情况下是不可能的。

上周我发现这个应用程序正是这样做的。 http://itunes.apple.com/us/app/dataman-real-time-data-usage/id393282873?mt=8

它在后台运行并跟踪您使用的蜂窝网络/WiFi 数据的数量。我怀疑开发人员正在将他的应用程序注册为跟踪位置更改,但在应用程序运行时位置服务图标不可见,我认为这是一个要求。

有没有人有任何关于如何实现这一点的线索?

最佳答案

我也见过这种行为。在尝试了很多之后,我发现了两件事,这可能会有所帮助。但我仍然不确定这会如何影响审查过程。

如果您使用其中一项后台功能,该应用程序将在退出(由系统)后再次由 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 套接字。但是这个 10 分钟回调提供了一个很好的副作用:在 10 分钟(有时更早)之后,我发现我的计时器和之前的运行步骤正在执行一小段时间。如果您将一些 NSLog(..) 放入您的代码中,您就可以看到这一点。这意味着,这个简短的“唤醒”会执行代码一段时间。根据 Apple 的说法,我们还有 30 秒的执行时间。我假设,像线程这样的后台代码被执行了将近 30 秒。这是有用的代码,如果您必须“有时”检查某些内容。

该文档说,如果应用程序终止,所有后台任务(VoIP、音频、位置更新)都将在后台自动重新启动。启动后,VoIP 应用程序将在后台自动启动!

通过滥用这种行为,你可以让你的应用看起来像“永远”运行。
注册一个后台进程(即 VoIP)。这将导致您的应用程序在终止后重新启动。

现在编写一些“任务必须完成”的代码。根据 Apple 的说法,您还有一些时间(5 秒?)来完成任务。我发现,这一定是 CPU 时间。所以这意味着:如果你什么都不做,你的应用程序仍在执行!如果您完成了工作,Apple 建议您调用到期处理程序。在下面的代码中,您可以看到,我在 expireHandler 上有一条评论。只要系统允许您的应用程序运行,这就会导致您的应用程序运行。所有计时器和线程都保持运行,直到 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 或其他应用程序之一,系统会在后台重新启动该应用程序,这将重新启动您的后台进程;-)
有了这个 PingPong,我可以做很多背景。但请记住要非常节省 CPU 时间。并保存所有数据,以恢复您的 View - 您的应用程序将在一段时间后终止。为了使它看起来仍在运行,您必须在唤醒后跳回到上一个“状态”。

我不知道这是否是您之前提到的应用程序的方法,但它对我有用。

希望我能帮上忙

更新:

测完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 expireHandler,您只需重新启动一个长时间运行的任务即可。此任务将在 600 秒后终止。但是将再次调用到期处理程序,这将启动另一个长时间运行的任务,等等。现在您只需检查应用程序返回前台的天气。然后关闭 bgTask,就大功告成了。也许一个人可以做某事。像这样在长时间运行的任务中的 expireHandler 里面。试试吧。使用您的控制台,看看会发生什么...玩得开心!

更新 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
});
}

这是在没有 VoIP 黑客的情况下工作的。根据文档,如果执行时间结束,将执行到期处理程序(在本例中为我的“expirationHandler”块)。通过将块定义为块变量,可以在到期处理程序中再次递归启动长时间运行的任务。这也会导致无休止的执行。

如果您的应用程序再次进入前台,请注意终止任务。如果您不再需要它,请终止该任务。

根据我自己的经验,我测量了一些东西。
在打开 GPS radio 的情况下使用位置回调会很快耗尽我的电池电量。使用我在更新 2 中发布的方法几乎不需要任何精力。根据“用户体验”,这是一种更好的方法。也许其他应用程序是这样工作的,将其行为隐藏在 GPS 功能背后......

关于iPhone - 后台轮询事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4656214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com