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.swift
的init()
方法中,执行:
_ = 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 中的服务或守护程序一样运行