iOS:让应用程序像服务一样运行

Posted

技术标签:

【中文标题】iOS:让应用程序像服务一样运行【英文标题】:iOS: Keep an app running like a service 【发布时间】:2012-06-18 03:14:52 【问题描述】:

ios 中,我将如何指示操作系统保持我的应用程序运行,即使它不再处于前台?

Skype Viber Empatica Zenly

还有更多的应用程序这样做。

【问题讨论】:

iOS 仅允许某些类型的应用程序执行此操作。您要编写什么样的应用程序需要在后台继续运行? 复制:***.com/questions/6287989/running-apps-in-background 如果您的问题与 voip-app 相关(因为您提到了 Skype),请查看此处的链接:***.com/a/11033929/653513 但后台的服务和应用程序并不完全相同。 【参考方案1】:

更新到 Swift 5

也许不是 OP 的正确答案。但这将帮助您在应用程序进入后台时启动background task。并在一段时间后被 iOS 杀死(希望在处理完成后)。

创建一个扩展

extension Notification.Name 
  @discardableResult
  func observe(using: @escaping (Notification) -> Void) -> NSObjectProtocol 
    return NotificationCenter.default.addObserver(forName: self,
                                                  object: nil,
                                                  queue: OperationQueue.main,
                                                  using: using)
  

声明一个变量

fileprivate let backgroundTaskStarter = 
  // TODO: If this doesn't work, switch to willResignActiveNotification.
  UIApplication.didEnterBackgroundNotification.observe()  _ in
    UIApplication.shared.beginBackgroundTask 
      print("endBackgroundTask called by iOS")
    
  
()

Filename.swiftinit() 方法中,执行:

_ = backgroundTaskStarter

【讨论】:

【参考方案2】:

基本上,iOS 中不存在服务类型的应用程序或功能。 即使是“后台”应用程序(UIBackgroundMode)也不能完全免费运行,并且不受其他操作系统上的服务或守护程序等限制。

这是关于后台执行以及通知和计时器等的情况。

1) 应用无法在后台执行,除非:

a) 它要求操作系统提供额外的时间来执行此操作。这是使用 beginBackgroundTaskWithExpirationHandler 完成的。 Apple 没有(有意)指定这个额外的时间有多长,但实际上它大约是 10 分钟。

b) 应用程序具有后台模式,这些模式是 VoIP、音频、位置、报摊。即使它具有这些类型之一,应用程序也无法不受限制地执行。本讨论的其余部分假设应用程序没有后台模式。如果您尝试使用其中一种后台模式来使您的应用能够在后台运行,但您的应用没有合法使用特定功能,那么您的应用将在应用商店提交时被拒绝(即拥有 UIBackgroundMode它必须是:VoIP 应用程序,需要持续更新位置,在后台连续播放音频的能力是一项基本功能,或者是报亭应用程序)。

2) 当一个应用程序被暂停时,它不能做任何事情来直接唤醒自己。它以前不能安排一个 NSTimer,它不能使用像 performSelector:afterDelay 这样的东西。等等

应用再次激活的唯一方法是用户采取措施使其激活。用户可以通过以下方式做到这一点:

a) 直接从应用程序图标启动应用程序

b) 启动应用以响应应用先前在其处于活动状态时安排的本地通知。

c) 启动应用程序以响应服务器发送的远程通知。

d) 其他一些:例如,如果应用程序注册为处理通过 URL 启动,则 URL 启动;或者如果它被注册为能够处理某种类型的内容。

如果本地/远程通知触发时应用程序处于前台,则应用程序会直接接收它。

如果触发本地/远程通知时应用当前不在前台,则应用不会收到它。通知触发时没有执行任何代码!

只有当用户选择通知时,应用才会激活并执行。

请注意,用户可以为整个设备或仅针对特定应用程序禁用通知,在这种情况下,用户将永远看不到它们。如果在通知即将触发时关闭设备,则会丢失。

IOS 7 更新

1) 有一些新的后台模式,例如后台获取(但是,您仍然不能被操作系统以确定性的方式唤醒)

2) 现在有后台推送通知

3) beginBackgroundTaskWithExpirationHandler 时间从 10 分钟减少到 3 分钟左右。

【讨论】:

voip 应用程序可以在后台运行(有一定的限制)——它们只需在操作系统中注册为 voip 应用程序(并且它们实际上必须提供 voip 功能,否则它们将无法通过审批流程) 现在,如果我不需要连续的位置更新,而是定期更新,是否会因为使用后台服务而拒绝应用程序,或者是否有不同的方式每 5-10 分钟唤醒应用程序或所以呢? @rokjarc,是的,正如我在回答中所说:“b)应用程序具有后台模式,模式为:voip ....” @Neo42 是的,情况仍然如此,关于地图,您是否阅读过 b) 的第一句话 “1) 应用程序无法在后台执行,除非:.... b) 应用程序具有后台模式,模式为:voip、音频、位置、报摊。”令人困惑?是什么让您认为应用显示的是蓝色条而不是操作系统。【参考方案3】:

现在 iOS7 发生了变化,现在是测试版

来自Apple's developer portal:

通过采用新的 iOS 7 中的多任务 API。新服务允许您的应用更新 信息和在后台下载内容而不会耗尽 不必要的电池。更新可能发生在机会主义 时间并根据使用情况智能安排,因此您的应用程序 可以在用户需要时在后台更新内容。

【讨论】:

【参考方案4】:

是的,我们可以这样做,

创建一个私有字段来跟踪我们的状态:

UIBackgroundTaskIdentifier _bgTask;

现在调用这个方法,像服务一样运行你的应用

if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) 

   _bgTask = UIBackgroundTaskInvalid;
   [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(doBackground:)
name:UIApplicationDidEnterBackgroundNotification object:nil];

现在创建一个选择器-

- (void) doBackground:(NSNotification *)aNotification

   UIApplication *app = [UIApplication sharedApplication];

   if ([app respondsToSelector:@selector(beginBackgroundTaskWithExpirationHandler:)])
   
      _bgTask = [app beginBackgroundTaskWithExpirationHandler:^
      
         dispatch_async(dispatch_get_main_queue(), ^
         
            if (_bgTask != UIBackgroundTaskInvalid)
            
               [app endBackgroundTask:_bgTask];
               _bgTask = UIBackgroundTaskInvalid;
            
         );
      ];
   

完成任务后,调用以下代码-

UIApplication *app = [UIApplication sharedApplication];
if ([app respondsToSelector:@selector(endBackgroundTask:)]) 

   if (_bgTask != UIBackgroundTaskInvalid)
   
      [app endBackgroundTask:_bgTask];
      _bgTask = UIBackgroundTaskInvalid;
   

【讨论】:

以上是关于iOS:让应用程序像服务一样运行的主要内容,如果未能解决你的问题,请参考以下文章

怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死

我可以让一些代码像守护进程一样在 Django 中不断运行吗

如何使 Python 脚本像 Linux 中的服务或守护程序一样运行

怎么让Android程序一直后台运行,像QQ一样不被杀死

iOS 如何让 UISlider 和 UIButton 像 Apple 的 Music 应用一样?

你如何让一个空的 UITextView 像 iOS 上的 Notes 一样滚动?