在后台更新 Xamarin.iOS 应用

后台刷新是唤醒挂起或未运行的应用程序并用新内容更新应用程序的过程。 iOS 提供三个选项用于在后台刷新内容:

  1. 区域监视重大位置更改服务 - 位置感知 API 根据用户位置的更改触发后台更新。 这些 API 可以随意用于刷新非基于位置的 iOS 6 应用程序中的内容,其中其他选项不可用。
  2. 后台提取 (iOS 7+) - 刷新频繁更新的非关键内容的临时方法。
  3. 远程通知 (iOS 7+) - 接收推送通知的应用程序可以使用通知来触发后台内容刷新。 此方法可用于更新需要零星更新的重要时间敏感内容。

以下部分介绍这些选项的基础知识。

区域监视和重大位置更改

iOS 提供两个具有后台功能的位置感知 API:

  1. 区域监视是设置具有边界的区域,并在用户进入或退出区域时唤醒设备的过程。 区域是圆形的,可以有不同大小。 当用户越过区域边界时,设备会唤醒以处理事件,通常是通过触发通知或启动任务。 区域监视需要 GPS,并增加电池和数据使用量。
  2. 重大位置更改服务是一种更简单的节能选项,可用于具有手机无线电的设备。 当设备切换单元塔时,将通知侦听重要位置更改的应用程序。 此服务可用于唤醒挂起或终止的应用程序,并提供在后台检查新内容的机会。 除非与后台任务配对,否则后台活动限制为大约 10 秒。

应用程序不需要位置 UIBackgroundMode 即可使用这些位置感知 API。 由于 iOS 不会跟踪设备因用户位置更改而唤醒设备时可以运行的任务类型,因此这些 API 提供了一个解决方法,用于更新 iOS 6 上后台的内容。 请记住,使用基于位置的 API 触发后台更新会利用设备资源,并可能会使不了解应用程序为何需要访问其位置的用户感到困惑。 在尚未使用位置 API 的应用程序中实现区域监视或重大位置更改时,请使用自由裁量权。

对后台处理使用位置监视的应用在 iOS 6 中暴露出缺陷:如果应用程序的需求不适合背景所需的类别,则其背景选项有限。 通过引入两个新的 API,后台提取远程通知,iOS 7(及更高)为更多应用程序提供了后台机会。 接下来的两个部分介绍了这些新 API。

后台提取(iOS 7 及更高)

在 iOS 6 中,一个进入前台的应用程序需要时间来加载新内容,简要演示用户已看到的内容。 后台提取允许应用程序在用户启动应用程序之前加载新数据,并为用户提供最新的内容。

若要实现后台提取,请编辑 Info.plist,并选中启用后台模式后台提取复选框:

Edit the Info.plist and check the Enable Background Modes and Background Fetch check boxes

接下来,FinishedLaunching重写 AppDelegate 方法以设置最小提取间隔。 在此示例中,我们让 OS 决定提取新内容的频率:

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
  UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval (UIApplication.BackgroundFetchIntervalMinimum);
  return true;
}

最后,通过在 AppDelegate 中重写 PerformFetch 方法并传入完成处理程序来执行提取。 完成处理程序是接受 UIBackgroundFetchResult 的委托:

public override void PerformFetch (UIApplication application, Action<UIBackgroundFetchResult> completionHandler)
{
  // Check for new data, and display it
  ...
  
  // Inform system of fetch results
  completionHandler (UIBackgroundFetchResult.NewData);
}

完成内容更新后,我们通过调用具有适当状态的完成处理程序来告知 OS。 iOS 提供三个选项用于完成处理程序状态:

  1. UIBackgroundFetchResult.NewData - 在提取新内容并更新应用程序时调用。
  2. UIBackgroundFetchResult.NoData - 在获取新内容但没有可用内容时调用。
  3. UIBackgroundFetchResult.Failed - 对于错误处理非常有用,当提取无法完成时,将调用它。

使用后台提取的应用程序可以调用以从后台更新 UI。 当用户打开应用时,UI 将更新并显示新内容。 这还会更新应用程序的应用切换器快照,以便用户可以查看应用程序何时包含新内容。

重要

调用 PerformFetch 后,应用程序大约需要 30 秒才能开始下载新内容,并调用完成处理程序块。 如果耗时太长,应用将终止。 下载媒体或其他大型文件时,请考虑将后台提取与后台传输服务搭配使用。

BackgroundFetchInterval

在上面的示例代码中,我们让 OS 通过将最小提取间隔设置为 BackgroundFetchIntervalMinimum 来确定提取新内容的频率。 iOS 为提取间隔提供三个选项:

  1. BackgroundFetchIntervalNever - 告诉系统从不提取新内容。 使用此选项可在某些情况下关闭提取,例如用户未登录时。 这是提取间隔的默认值。
  2. BackgroundFetchIntervalMinimum - 让系统根据用户模式、电池电量、数据使用情况和其他应用程序的需求来确定提取的频率。
  3. BackgroundFetchIntervalCustom - 如果知道应用程序内容更新的频率,可以在每次提取后指定“睡眠”间隔,在此期间,应用程序将阻止提取新内容。 该间隔启动后,系统将确定何时提取内容。

BackgroundFetchIntervalMinimumBackgroundFetchIntervalCustom 都依赖于系统来计划提取。 此间隔是动态的,适合设备的需求以及单个用户的习惯。 例如,如果一个用户每天早上检查一个应用程序,另一个用户每小时检查一次,iOS 将确保每次打开应用程序时,这两个用户的内容都是最新的。

后台提取应用于经常使用非关键内容更新的应用程序。 对于具有关键更新的应用程序,应使用远程通知。 远程通知基于后台提取,并共享相同的完成处理程序。 接下来,我们将深入了解远程通知。

远程通知(iOS 7 及更高)

推送通知是通过 Apple 推送通知服务 (APNs) 从提供程序发送到设备的 JSON 消息。

在 iOS 6 中,传入的推送通知告知系统提醒用户应用程序中发生了一些有趣的事情。 单击通知会将应用程序从挂起或终止的状态拉取出来,应用将开始更新内容。 iOS 7(及更高版本)通过让应用程序有机会更新后台中的内容,然后通知用户,以便用户可以打开应用程序并立即显示新内容来扩展普通推送通知。

若要实现远程通知,请编辑 Info.plist 并选中启用后台模式远程通知复选框:

Background Mode set to Enable Background Modes and Remote notifications

接下来,将推送通知本身上的 content-available 标志设置为 1。 这让应用程序知道在显示警报之前提取新内容:

'aps' {
  'content-available': 1,
  'alert': 'Something new has happened in your app!''
}

AppDelegate中,重写 DidReceiveRemoteNotification 方法以检查可用内容的通知有效负载,并调用相应的完成处理程序块:

public override void DidReceiveRemoteNotification (UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
  if([content-available]) {
    // fetch content
    completionHandler (UIBackgroundFetchResult.NewData);
  }
}

应将远程通知用于对应用程序功能至关重要的非经常性更新内容。 有关远程通知的详细信息,请参阅 iOS 指南中的 Xamarin 推送通知。

重要

由于远程通知中的更新机制基于后台提取,因此应用程序必须开始下载新内容,并在接收通知 30 秒内调用完成处理程序块,否则 iOS 将终止应用程序。 在后台下载媒体或其他大型文件时,请考虑将远程通知与后台传输服务配对。

无提示远程通知

远程通知是一种通知应用程序更新并开始提取新内容的简单方法,但在某些情况下,我们不需要通知用户某些内容已更改。 例如,如果用户标记文件进行同步,则无需在每次更新文件时通知它们。 文件同步不是一个令人惊讶的事件,也不需要用户的立即注意。 用户只需期望文件在打开文件时是最新的。

对于上述情况,iOS 允许以无提示方式发送推送通知,即没有警报。 若要将常规通知转换为无提示通知,只需从通知有效负载中删除警报:

'aps' {
  'content-available': 1
}

速率限制

从开发人员的角度来看,正常通知和无提示通知之间的最大区别是无提示推送速率有限。 如果推送速率过高,APNs 将延迟向设备传送无提示推送。 这是为了确保应用程序不会消耗过多无提示通知的设备资源。

不过,APNs 会让无声通知 "搭载 "正常远程通知或 keep-alive 响应。 由于常规通知速率不受限制,因此可用于将存储的无提示通知从 APNs 推送到设备,如下图所示:

Regular notifications can be used to push stored silent notifications from the APNs to the device, as illustrated by this diagram

重要

Apple 鼓励开发人员每当应用程序需要时发送无提示推送通知,并允许 APNs 安排其交付。

在本部分中,我们介绍了用于刷新后台内容的各种选项,以运行不适合背景必需类别的任务。 现在,让我们看看其中一些运行中的 API。

下一部分:第 4 部分 - iOS 后台演练