iOS动作扩展中的后台任务

问题描述 投票:15回答:3

我正在为应用程序创建一个动作扩展,为用户准备一些数据,然后使用MailCore2将此信息发送到SMTP服务器。准备数据的速度非常快,但发送电子邮件可能需要一些时间(取决于其大小)。这就是为什么我正在寻找一种在后台处理发送活动的方法。但这导致了不同解决方案的一些问题:

  1. 使用URLSession。这是在iOS扩展中处理大型上传或下载的第一种方法。但问题是MailCore2不使用URLSessions将数据传输到邮件服务器。所以这不可用。或者是否有可能以某种方式在URLSession中“包装”此调用?
  2. 使用UNUserNotificationCenter并在数据准备后从扩展发送本地通知。我们的想法是在收到此通知后在主应用程序中启动发送任务。问题:仅当用户单击通知时才会调用通知userNotificationCenter didReceive方法。简单的徽章通知不会调用委托方法。
  3. 使用后台提取。这在模拟器中工作正常,但在iOS设备上连接到SMTP服务器时出错。我遇到了github.com/MailCore/mailcore2/issues/252中描述的同样的HELO问题。对于此问题,解决方案应该是MCOSMTPSession.isUseHeloIPEnabled = true,但这可能不适用于所有服务器。所以也不是一个完美的解决方案

任何想法,如何处理这样的任务?或者如何处理上述解决方案之一?

编辑:因为这个问题还没有收到任何答案:什么不清楚或需要哪些附加信息?

ios swift ios-app-extension mailcore2
3个回答
4
投票

看起来你无法在扩展后台中安排长时间运行的运行任务。请查看here(Some APIs Are Unavailable to App Extensions)

在您建议的解决方案中,我的建议是尝试使用silent push notifications,您可以在准备数据阶段调用api,然后从服务器发送静默推送并在静默推送到达时执行后台任务。


2
投票

从您的回答来看,您的困难在于您需要允许后台活动。你可以通过following a tutorial such as this one做到这一点。


2
投票

最有用的解决方案是使用推送通知。我在自己的应用程序中使用的解决方案:

  1. 创建一个简单的服务器,可以检索一个简单的请求:设备令牌和您想要唤醒设备的时间。
  2. 当应用程序进入后台模式时,将请求发送到服务器以便稍后唤醒设备。例如。 5分钟/ 20分钟,等func applicationWillEnterForeground(_ application: UIApplication) { AppDelegate内。
  3. 不要忘记允许应用程序尽可能在后台运行。

例如,

   @UIApplicationMain
    class AppDelegate: UIResponder {
    var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
    func application(_ application: UIApplication,
                         didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                         fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
            if UIApplication.shared.applicationState != .active {
                doFetch(completionHandler: completionHandler)
            } else {
                // foreground here
                completionHandler(UIBackgroundFetchResult.noData)
            }
        }
    func application(_ application: UIApplication,
                         performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
            doFetch(completionHandler: completionHandler)
        }
    private func doFetch(completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    sendTheRequestToWakeApp()
    backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
                self?.endBackgroundTask()
            }
/// do work here
    completionHandler(UIBackgroundFetchResult.noData)
    }
    private func endBackgroundTask() {
            print("Background task ended.")
            UIApplication.shared.endBackgroundTask(backgroundTask)
            backgroundTask = UIBackgroundTaskInvalid
        }
    private func sendTheRequestToWakeApp() {
    /// Implement request using native library or Alamofire. etc.
    }
    }

在服务器端使用简单的时间或循环。

缺点,

  1. 互联网是必需的
  2. 它并不完美。电池电量不足时,后台模式受限制。

不要忘记设置项目:

proejct screenshot

© www.soinside.com 2019 - 2024. All rights reserved.