为了账号安全,请及时绑定邮箱和手机立即绑定

iphone-背靠背为事件进行投票

iphone-背靠背为事件进行投票

iOS
凤凰求蛊 2019-07-25 14:09:04
iphone-背靠背为事件进行投票很长一段时间以来,我一直在研究一种在我的iPhone应用程序中每隔X分钟轮询一次数据计数器的方法。在阅读了大量的后台执行文档和一些试用应用程序之后,我认为在不滥用后台API的情况下,这是不可能的。上周,我发现这个应用程序就是这么做的。http:/itunes.apple.com/us/app/DataMan-实时-数据-使用/id3932873?mt=8它在后台运行,并跟踪您所使用的蜂窝/WiFi数据的计数。我怀疑开发人员正在注册他的应用程序以跟踪位置变化,但是在应用程序运行时,位置服务图标是不可见的,我认为这是必需的。有没有人知道如何做到这一点?
查看完整描述

3 回答

?
梦里花落0921

TA贡献1772条经验 获得超5个赞

我也见过这种行为。经过多次尝试,我发现了两件事情,这可能会有所帮助。但我仍不清楚这会如何影响检讨过程。

如果您使用其中一个后台功能,应用程序将由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功能后面.




查看完整回答
反对 回复 2019-07-26
?
慕仙森

TA贡献1827条经验 获得超7个赞

什么起作用,什么不起作用

现在还不完全清楚这些答案中的哪一个有效&我浪费了大量的时间来尝试它们。以下是我对每一种策略的经验:

  1. 网络电话攻击-工作,但是

    将要

    如果你不是VOIP应用程序,就会被拒绝
  2. 递归

    beginBackgroundTask...

    -不起作用。10分钟后它就会退出。即使您尝试了注释中的修补程序(至少是截至2012年11月30日的注释)。
  3. 无声的音频作品,但是人们因为这个而被拒绝。
  4. 本地/推送通知-在您的应用程序被唤醒之前需要用户交互
  5. 使用背景位置-作品

    ..详情如下:

基本上,您使用“位置”后台模式,以保持您的应用程序在后台运行。它确实有效,即使用户不允许位置更新。即使用户按下HOME按钮并启动另一个应用程序,您的应用程序也将继续运行。如果你的应用程序与位置无关的话,这也是一个电池消耗器&如果你的应用程序与位置无关的话,这可能是审批过程中的一个环节,但据我所知,这是唯一一个很有可能获得批准的解决方案。

下面是它的工作原理:

在你的褶皱里:

  • 应用程序不在后台运行:否
  • 所需背景模式:地点

然后参考CoreLocation框架(在构建阶段),并在应用程序中的某个地方添加这段代码(在它进入后台之前):

#import <CoreLocation/CoreLocation.h>CLLocationManager* locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];

注:startMonitoringSignificantLocationChanges将要工作。

值得一提的是,如果你的应用程序崩溃,iOS就不会让它复活。VOIP黑客是唯一能把它带回来的黑客。




查看完整回答
反对 回复 2019-07-26
  • 3 回答
  • 0 关注
  • 291 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信