在后台运行应用程序超过 10 分钟
Posted
技术标签:
【中文标题】在后台运行应用程序超过 10 分钟【英文标题】:Run app for more than 10 minutes in background 【发布时间】:2012-03-16 13:52:10 【问题描述】:当 ios 应用程序进入后台状态时,我正在尝试将其保持在活动状态超过 10 分钟。
我该如何实现。
【问题讨论】:
@RichardJ.RossIII nop,他想在应用程序处于后台而不是后台线程时运行代码。 【参考方案1】:请参阅iPhoneAppProgrammingGuide 的“后台执行”部分。简而言之,您的应用必须是以下类型之一:
在后台向用户播放有声内容的应用,例如音乐播放器应用 让用户随时了解其位置的应用,例如导航应用 支持互联网协议语音 (VoIP) 的应用 需要下载和处理新内容的报亭应用 从外部附件接收定期更新的应用并且您必须按如下方式添加到 Info.plist: 将 UIBackgroundModes 键添加到您的 Info.plist 文件并将其值设置为包含以下一个或多个字符串的数组:
音频 - 应用程序在后台向用户播放可听内容。 (此内容包括使用 AirPlay 的流式音频或视频内容。) 位置 - 该应用让用户随时了解他们的位置,即使在后台运行时也是如此。 voip - 该应用使用户能够使用互联网连接拨打电话。 newsstand-content - 该应用程序是下载和处理杂志或报纸的报亭应用程序 背景中的内容。 external-accessory - 该应用程序与需要在 通过外部附件框架定期安排。 bluetooth-central — 该应用程序与蓝牙配件配合使用,该配件需要在 通过 CoreBluetooth 框架定期安排请注意,审核过程的一部分将检查以确保您的应用在后台处理方面按照它所说的那样做。
【讨论】:
请注意,仅设置这些类型不会使应用程序本身保持活力。例如:当您播放音频时,它会在音乐期间保持活跃。但是当您的歌曲结束时,该应用仍然可以暂停。 如果我想运行警报,一旦收到通知,当应用程序在后台时,我该如何播放音乐??这段时间可以超过 1 小时 @Mr.G:你的问题找到解决方案了吗?【参考方案2】:这是我使用 beginBackgroundTaskWithExpirationHandler 所做的。
编写一个启动后台任务的方法。 在该后台任务中,运行NSTimer
,计划(非重复)时间小于 10 分钟。就我的情况而言,我使用了 5 分钟。
一旦NStimer
的选择器触发,结束后台任务,然后立即调用您之前编写的方法来启动另一个后台任务。
如果您想安排方法在特定时间运行,您必须在后台任务中检查它们。
这个解决方案不是很理想,而且仍然很耗电,但会做你想做的事。
编辑:从iOS7开始,我建议你阅读这个excellent post。请注意,这篇文章最后一次更新是在 2013 年,现在可能已经无关紧要了。
【讨论】:
Apple 是否批准此应用在 App Store 上架? 是的。我不知道这是否有帮助,但我将它作为“省电”模式发布,以替代我们一直在运行 GPS 以保持应用程序在后台运行的模式,但用户现在可以选择。因此,我仍然保留了他们让您披露的“GPS 会显着降低电池寿命”的消息。 我原本打算使用 GPS 来保持应用程序的运行,但这种方法对我来说更好,因为这样我就不必要求使用该人的位置了。非常感谢您解释您的方案。 @ing0 更新:我尝试了几种代码组合,但似乎无法让我的应用程序无限期地在后台运行(使用此方法)。你有任何工作代码吗? @AbhishekThapliyal 我已经回复了。我已经有一段时间没有这样做了,但我认为我的回答会有所帮助。【参考方案3】:仅允许某些类型的应用在后台运行。请参阅this guide 的“实现长时间运行的后台任务”部分。
如果您不请求进行后台处理的权限,您可以使用 UIApplication 的beginBackgroundTaskWithExpirationHandler,但您无法获得额外的时间。
【讨论】:
【参考方案4】:此代码使您的 iOS 应用程序在后台无限期运行。将以下方法复制并粘贴到单例/管理器中,该管理器处理您需要在后台执行的任务。
// @interface
// Declare Private property
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
//@end
// ...
// Copy into
//@implementation
- (void)setupBackgrounding
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appBackgrounding:)
name: UIApplicationDidEnterBackgroundNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appForegrounding:)
name: UIApplicationWillEnterForegroundNotification
object: nil];
- (void)appBackgrounding: (NSNotification *)notification
[self keepAlive];
- (void) keepAlive
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
[self keepAlive];
];
- (void)appForegrounding: (NSNotification *)notification
if (self.backgroundTask != UIBackgroundTaskInvalid)
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
【讨论】:
不幸的是,在 iOS7 上这对我来说只能工作大约三分钟。 其实很多物联网商业应用都在用这个。 苹果会拒绝这个应用吗? 它的代码仅适用于 iOS 7 及更高版本的 3 分钟。我也使用 iOS 9 和 iOS 10 进行了检查。【参考方案5】:你不能。除非您的应用程序使用音频、voip 或 gps。您可以做的是通知用户(通过本地通知)时间快到了,并要求他打开/关闭应用程序。
另外,如果你只需要通知用户,你可以使用推送通知。
【讨论】:
【参考方案6】:https://github.com/yarodevuci/backgroundTask 在这里检查我的代码 我正在使用播放空白 wav 文件的音频播放器 在 IOS 8 上完美运行 24 小时内电池使用量约为 10% 使用方法:
var backgroundTask = BackgroundTask()
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background.
backgroundTask.stopBackgroundTask() //Stops the task
警告:如果您尝试提交,Apple 将拒绝此!
【讨论】:
【参考方案7】:如果您的应用类型不是 VOIP/Audio/Location....(检查 Background Modes)之一,
或者您不想将您的 App 指定为后台 App,您可以实现 beginBackgroundTaskWithName:expirationHandler 或 beginBackgroundTaskWithExpirationHandler 以要求更多时间来运行您的进程背景。可以找到详细说明here
移动到后台的应用程序应尽快将自己置于静止状态,以便系统可以暂停它们。如果您的应用程序正在执行任务并且需要一些额外的时间来完成该任务,它可以调用 UIApplication 对象的 beginBackgroundTaskWithName:expirationHandler: 或 beginBackgroundTaskWithExpirationHandler: 方法来请求一些额外的执行时间。调用这些方法中的任何一个都会暂时延迟您的应用程序的暂停,给它一点额外的时间来完成它的工作。完成这项工作后,您的应用必须调用 endBackgroundTask: 方法让系统知道它已完成并且可以暂停。
对 beginBackgroundTaskWithName:expirationHandler: 或 beginBackgroundTaskWithExpirationHandler: 方法的每次调用都会生成一个唯一的令牌以与相应的任务相关联。当你的应用完成一个任务时,它必须调用 endBackgroundTask: 方法并带有相应的令牌,让系统知道任务已经完成。未能为后台任务调用 endBackgroundTask: 方法将导致您的应用程序终止。如果您在启动任务时提供了过期处理程序,系统会调用该处理程序并给您最后一次机会来结束任务并避免终止。
【讨论】:
以上是关于在后台运行应用程序超过 10 分钟的主要内容,如果未能解决你的问题,请参考以下文章