【问题标题】:iOS Background downloads when the app is not active应用未激活时 iOS 后台下载
【发布时间】:2012-02-10 07:04:57
【问题描述】:

最初下载我的应用时,用户需要下载一个大文件,例如 200MB(上限)。我绝对不能指望用户在下载此文件之前保持应用程序打开。所以他/她可能会关闭应用程序,应用程序将进入后台。

在这种情况下如何继续下载文件?这在 iOS 中是否可行?

【问题讨论】:

  • 见下方 MMR 的回答。真实背景NSURLSession 是当今实现这一目标的最佳方式。所有这些其他答案都早于这种技术。如果你有一个需要不到 3 分钟完成的小下载,后台任务是不错的方法,但对于大后台下载,请使用后台 NSURLSession

标签: objective-c ios ios5 background download


【解决方案1】:

在您的- (void)applicationDidEnterBackground:(UIApplication *)application下面添加

UIApplication  *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
        [app endBackgroundTask:bgTask]; 
}];

你很高兴......我在我发布的下载管理器应用程序之一中有这个

这会很好用。您还可以检查您有多少时间,因为苹果只启用 10 分钟的后台任务。使用:

NSTimeInterval ti = [[UIApplication sharedApplication]backgroundTimeRemaining];
NSLog(@"backgroundTimeRemaining: %f", ti); // just for debug

【讨论】:

  • 这样我可以下载吗?像上面@nick 所说的那样有时间限制吗?
  • 是的..苹果谈到了时间限制..但我可以用上面的代码下载一个大小为 800 mb 的文件..并且该应用程序在应用商店中..
  • 哇!!你的评论是宝贵的信息@Saurabh。谢谢!!
  • @samfisher - 如果您认为我的评论有宝贵的信息.. 那么为什么不点击 upvote 链接并给我一些声誉.. :) :)
  • 如果应用在后台运行超过 10 分钟,iOS 将终止您的应用。因此,如果用户的网络很慢,它将无法正常工作。
【解决方案2】:

开始下载时可以启动后台任务:

正在过渡到后台的应用可以请求额外的 完成任何重要的最后一分钟任务的时间。

Executing a Finite-Length Task in the Background

但是,这样的任务受限于系统未定义的执行时间。但是,在这种情况下,下载 200Mb 的文件可能是一项太大的任务。

【讨论】:

  • 是的。您可能想考虑使用允许您暂停和从中断处继续下载的网络库,因此如果下载中断,用户不必从头开始重新开始。 ASIHttpRequest 可以做到这一点,但不再支持它,因为它不适用于 ARC。
  • 那不再正确了。在 ASIHttp 的 ARC 上,您可以使用在非 ARC 环境下编译的静态库。
【解决方案3】:

您可以使用 iOS 7.0 及更高版本中引入的 NSURLSession 来继续上传/下载文件,即使应用程序暂停。

Apple documentation

NSURLSession 类和相关类为 下载内容。该 API 提供了一组丰富的委托方法 用于支持身份验证并使您的应用能够 当您的应用程序未运行时执行后台下载,或者在 iOS 中, 当您的应用暂停时。

后台会话可让您执行内容的上传和下载 在您的应用未运行时在后台运行。您可以创建一个 通过调用后台会话配置 backgroundSessionConfiguration:方法在 NSURLSessionConfiguration 类。

link 上一个很酷的使用 NSURLSession 的教程。

【讨论】:

  • 这是正确答案。使用背景NSURLSession!其他答案早于这种技术,但现在这是完成可能超过UIBackgroundTask 方法允许的 3 分钟的长时间下载的最佳方法。
【解决方案4】:

在我的一个应用程序中,我正在加载大量数据。在下载数据之前,我绝对不能指望用户将应用程序保持在前台。我只是使用以下代码在应用程序处于后台时获取数据下载。它工作正常:-)
请执行以下步骤:

1) 在 ViewController 的头文件中使用以下行

   @property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;

在 .m 文件中合成它。

2) 在 ViewDidLoad 中分配 UIBackgroundTaskIdentifier 如下:

   self.backgroundTask = UIBackgroundTaskInvalid;

3) 使用以下代码行,这里我只是在 beginBackgroundTaskWithExpirationHandler: 块中保留 getDataFromServer 方法。

        self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
    }];

    /* Here your downloading Code, let say getDataFromServer method */

    [self getDataFromServer]; // Its dummy method

    /* Your downloading Code End Here */

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
    });

4) 如果要查看后台下载数据的剩余时间,请在 applicationDidEnterBackground:(UIApplication *)AppDelegate 的应用程序委托方法中包含以下行:

      NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);

【讨论】:

    【解决方案5】:

    AFNetworking 允许您在后台执行繁重的操作。

    AFNetworking 库是 NSURLConnection 和 NSOperationQueue 的完美结合。此库用于异步在后台下载不影响其他应用程序。

    AFNetworking 允许您使用 ExpirationHandle 处理下载,即如果在下载过程中连接丢失,它将再次连接到它。

    库来源AFNetworking

    参考来源 AFNetworking works in Background

    Apple 参考链接 Apple

    后台执行和多任务处理Apple

    【讨论】:

      【解决方案6】:
      #pragma mark - View Loading handling
      - (void)viewDidLoad
      {
          [super viewDidLoad];
          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
      }
      
      #pragma mark - Background handling when application goes background
      UIBackgroundTaskIdentifier background_task;
      - (void)appDidEnterBackground:(NSNotification *)notification {
          UIApplication  *application = [UIApplication sharedApplication];
          if([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
          {
              NSLog(@"Multitasking Supported");
              if (background_task == UIBackgroundTaskInvalid) {
                  background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
                      NSLog(@"Background task expiration\n");
                      //Clean up code. Tell the system that we are done.
                      [application endBackgroundTask: background_task];
                      background_task = UIBackgroundTaskInvalid;
                  }];
                  //To make the code block asynchronous
                  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                      //### background task starts
                      NSLog(@"Running in the background\n");
                      for(int cnt=0; cnt<10; cnt++) //while(TRUE)
                      {
                          NSLog(@"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
                          [NSThread sleepForTimeInterval:1]; //wait for 1 sec
                      }
                      //#### background task ends
                      //Clean up code. Tell the system that we are done.
                      NSLog(@"here you can do something before it really enters background");
                      [NSThread sleepForTimeInterval:1]; //wait for 1 sec
                      [application endBackgroundTask: background_task];
                      background_task = UIBackgroundTaskInvalid;
                  });
              }
              else
              {
                  NSLog(@"Multitasking Not Supported");
              }
          }
      }
      

      您可以通过此slide了解更多信息。
      我只是从这张幻灯片的 sn-p 中做了一些简单有用的修改。 希望这会有所帮助。

      【讨论】:

        【解决方案7】:

        构建一个 newsStand iOS 应用程序;不是标准的 iOS 应用程序。

        标准 iOS 应用程序:

        • 关闭时无法下载数据。
        • 推送到后台可以限时下载数据。
        • 没有足够的时间下载 200mb。

        NewsStand 应用程序在关闭或处于后台时有额外的下载时间特权。 每 24 小时一次,他们有权应答 remoteContentReady 委托呼叫。

        构建 newsStand 应用程序与构建标准 iOS 应用程序没有什么不同。您只需将其标记为 newStand 应用程序。

        然后您将有权运行 remoteContentReady 委托中的代码。

        要接收 remoteContentReady 信号,您必须从服务器端(c#、php、bla bla)发送一个信号。

        并非适用于每个 iOS 应用。类似于 remoteNotification 信号。您可能需要对您的网站进行 ssl 认证才能完成此操作。

        最好的问候

        【讨论】:

          【解决方案8】:

          不幸的是,这里的大多数答案在 2020 年都已过时! iOS 13 将-beginBackgroundTaskWithExpirationHandler: 的时间从几分钟减少到几秒钟,并且还会杀死应用程序并产生不利影响。我还考虑在下载期间禁用自动屏幕保护程序模式。更多信息可以在这里找到:

          【讨论】:

            猜你喜欢
            • 2011-06-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-07-10
            • 1970-01-01
            • 1970-01-01
            • 2017-09-26
            • 2021-10-30
            相关资源
            最近更新 更多