App Center Distribut – iOS 应用内更新

重要

Visual Studio App Center 于 2025 年 3 月 31 日停用,但分析和诊断功能除外,这些功能将继续受支持,直到 2026 年 6 月 30 日。 了解详细信息

通过 App Center Distribut 分发应用时,用户可安装新版本的应用。 随着应用的新版本可用,SDK 将向用户显示更新对话框,以便下载或推迟新版本。 选择更新后,SDK 将开始更新应用程序。

注释

使用应用内更新时需要考虑以下事项:

  1. 如果你已在 App Store 中发布应用,应用内更新将被禁用。
  2. 如果运行的是自动化 UI 测试,启用的应用内更新将阻止自动化 UI 测试,因为它们将尝试针对 App Center 后端进行身份验证。 建议不要为 UI 测试目标启用 App Center Distribute。

注释

在 App Center 的 4.0.0 版本中引入了中断性变更。 按照 “迁移到 App Center SDK 4.0.0 及更高” 章节从以前的版本迁移 App Center。

重要

App Center SDK 不支持 iOS 13 中引入的多个窗口应用。

在你的应用中添加应用内更新功能

如果尚未在应用程序中配置 SDK,请按照 “入门 ”部分进行作。

1.添加 App Center Distribute 模块

App Center SDK 是采用模块化方法设计的 , 只需集成你感兴趣的服务的模块。

通过 Cocoapods 集成

如果要通过 Cocoapods 将 App Center 集成到应用中,请将以下依赖项添加到 podfile 并运行 pod install

pod 'AppCenter/Distribute'

通过 Carthage 集成

  1. 将以下依赖项添加到Cartfile中,以包含 App Center Distribute。

    # Use the following line to get the latest version of App Center
    github "microsoft/appcenter-sdk-apple"
    
    # Use the following line to get the specific version of App Center
    github "microsoft/appcenter-sdk-apple" ~> X.X.X
    
  2. 运行 carthage update

  3. 打开应用程序目标的 “常规 设置”选项卡。将 AppCenterDistribute.framework 文件从 Carthage/Build/iOS 文件夹拖放到 XCode 中的 “链接框架和库 ”部分。

  4. AppCenterDistributeResources.bundleAppCenterDistribute.framework 拖放到 XCode 的项目导航器中。

  5. 对话框将出现,确保你的应用目标被选中。 然后单击“完成”。

通过 Swift 包管理器集成

  1. 在 Xcode 菜单中,单击“ 文件 > Swift 包 > 添加包依赖项”。
  2. 在出现的对话框中,输入存储库 URL: https://github.com/microsoft/appcenter-sdk-apple.git
  3. “版本”中,选择 “升级到下一个主要版本”,并采用默认选项。
  4. “程序包产品”列中选择 AppCenterDistribute

通过将二进制文件复制到项目中进行集成

如果不想使用 Cocoapods,可以通过将二进制文件复制到项目中来集成模块。 请遵循以下步骤:

注释

App Center SDK 支持使用 XCframework。 如果要将 XCframeworks 集成到项目中,请从发布页下载 AppCenter-SDK-Apple-XCFramework.zip 并将其解压缩。 生成的文件夹内容并不特定于任何平台,而是包含每个模块的XC框架。 它们可以按照通常的方式进行集成,如下所示。

  1. 下载以 zip 文件的形式提供的 App Center SDK 框架。

  2. 解压缩该文件,你将看到一个名为 AppCenter-SDK-Apple/iOS 的文件夹,其中包含每个 App Center 服务的不同框架。 项目中需要调用 AppCenter 的框架,因为它包含在不同模块之间共享的代码。

  3. [可选]为第三方库创建子目录。

    • 最佳做法是,第三方库通常位于子目录中,通常称为 Vendor。 如果项目未使用库的子目录进行组织,请立即创建 供应商 子目录。
    • 在 Xcode 项目中创建一个名为 Vendor 的组,以模拟磁盘上的文件结构。
  4. 打开 Finder,并将解压缩的 AppCenter-SDK-Apple/iOS 文件夹复制到项目的文件夹(位于所需位置)。

  5. 将 SDK 框架添加到 Xcode 中的项目:

    • 确保项目导航器可见(⌘+1)。
    • 现在,将 AppCenter.frameworkAppCenterDistribute.frameworkAppCenterDistributeResources.bundle 从 Finder( 供应商 文件夹中的捆绑包)拖放到 Xcode 的项目导航器中。 启动 SDK 需要 AppCenter.framework。 请确保已将其添加到项目,否则其他模块将不起作用,并且项目无法成功编译。
    • 对话框将出现,确保你的应用目标被选中。 然后单击“完成”。

2. 启动 App Center 分发

App Center 仅使用在应用程序中调用的特定模块。 在启动 SDK 时,必须显式调用它们中的每一个。

2.1 添加 App Center Distribut 的导入

在 Swift 中 Objective-C 或 AppDelegate.swift 文件中打开项目的 AppDelegate.m 文件,并添加以下导入语句:

@import AppCenter;
@import AppCenterDistribute;
import AppCenter
import AppCenterDistribute

2.2 添加 start:withServices: 方法

Distribute 添加到 start:withServices: 方法中以启动 App Center 分发服务。

在项目的 AppDelegate.m 类中插入以下行,以启动 SDK for Objective-C,或在 AppDelegate.swift 类的 didFinishLaunchingWithOptions 方法中插入以启动 Swift SDK。

[MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACDistribute class]]];
AppCenter.start(withAppSecret: "{Your App Secret}", services: [Distribute.self])

请确保已经在上面的代码示例中将 {Your App Secret} 替换为您的应用机密。 如果尚未在应用程序中配置 SDK,请查看 “入门 ”部分。

2.3 修改项目的 Info.plist

  1. 在项目的 Info.plist 文件中,单击顶部“信息属性列表”旁边的“+”按钮,添加一 URL types 个新键。 如果 Xcode 将 Info.plist 显示为源代码,请参阅以下提示。
  2. 将键类型更改为 Array。
  3. 向数组(Item 0)添加新条目,并将类型更改为 Dictionary。
  4. 在下方 Item 0,添加一个 URL Schemes 键并将类型更改为 Array。
  5. URL Schemes 密钥下,添加新条目(Item 0)。
  6. URL Schemes>Item 0 下,将值更改为 appcenter-{APP_SECRET},并将 {APP_SECRET} 替换为您应用的应用机密。

小窍门

如果要验证是否正确修改了 Info.plist,请将其作为源代码打开。 它应包含以下条目,其中使用你的应用密钥代替{APP_SECRET}

<key>CFBundleURLTypes</key>
<array>
  <dict>
  	<key>CFBundleURLSchemes</key>
  	<array>
  		<string>appcenter-{APP_SECRET}</string>
  	</array>
  </dict>
</array>

使用私人分发组

默认情况下,分发使用公共分发组。 如果要使用私有通讯组,则需要通过 updateTrack 属性显式设置它。

MSACDistribute.updateTrack = MSACUpdateTrackPrivate;
Distribute.updateTrack = .private

注释

默认值是 UpdateTrack.public。 此属性只能在AppCenter.start方法调用之前更新。 当应用程序进程重启时,不会保留对更新跟踪的更改,因此,如果属性在调用之前 AppCenter.start 并不总是更新,则默认情况下它将是公共的。

此调用后,将打开浏览器窗口以对用户进行身份验证。 所有后续更新检查都将在私有更新通道获取最新版本。

如果用户处于 专用轨道上,这意味着在成功进行身份验证后,他们将从他们所属的任何专用通讯组获取最新版本。 如果用户处于 公共轨道上,则意味着他们将从任何公共通讯组获取最新版本。

禁用自动更新检查

默认情况下,SDK 会自动检查新版本:

  • 应用程序启动时。
  • 当应用程序进入后台后,再次切换到前台。
  • 当启用之前已禁用的分发模块时。

如果你希望手动检查新版本,可以禁用自动检查更新。 为此,在 SDK 启动之前调用以下方法:

[MSACDistribute disableAutomaticCheckForUpdate];
Distribute.disableAutomaticCheckForUpdate()

注释

在调用 AppCenter.start 方法之前,必须调用此方法。

然后,可以使用以下部分中介绍的 checkForUpdate API。

手动检查更新

[MSACDistribute checkForUpdate];
Distribute.checkForUpdate()

这会向 App Center 发送请求,并在有新版本可用时显示更新对话框。

注释

即使启用了自动更新,更新调用的手动检查也有效。 如果另一个检查已完成,则忽略更新的手动检查。 如果用户已推迟更新(除非最新版本是强制更新),则不会处理更新的手动检查。

自定义或本地化应用内更新对话框

1.自定义或本地化文本

如果要本地化更新对话框中显示的文本,可以轻松提供自己的资源字符串。 查看 此字符串文件。 使用相同的字符串名称/键,并指定要反映在你自己的应用字符串文件中的对话框中的本地化值。

2.自定义更新对话框

可以通过实现 DistributeDelegate 协议来自定义默认更新对话框的外观。 在启动 SDK 之前,需要注册委托,如以下示例所示:

[MSACDistribute setDelegate:self];
Distribute.delegate = self;

下面是将 SDK 对话框替换为自定义对话框的委托实现示例:

- (BOOL)distribute:(MSACDistribute *)distribute releaseAvailableWithDetails:(MSACReleaseDetails *)details {

  // Your code to present your UI to the user, e.g. an UIAlertController.
  UIAlertController *alertController = [UIAlertController
      alertControllerWithTitle:@"Update available."
                       message:@"Do you want to update?"
                preferredStyle:UIAlertControllerStyleAlert];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Update"
                                         style:UIAlertActionStyleCancel
                                       handler:^(UIAlertAction *action) {
                                         [MSACDistribute notifyUpdateAction:MSACUpdateActionUpdate];
                                       }]];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Postpone"
                                         style:UIAlertActionStyleDefault
                                       handler:^(UIAlertAction *action) {
                                         [MSACDistribute notifyUpdateAction:MSACUpdateActionPostpone];
                                       }]];

  // Show the alert controller.
  [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];
  return YES;
}
func distribute(_ distribute: Distribute, releaseAvailableWith details: ReleaseDetails) -> Bool {

  // Your code to present your UI to the user, e.g. an UIAlertController.
  let alertController = UIAlertController(title: "Update available.",
                                        message: "Do you want to update?",
                                 preferredStyle:.alert)

  alertController.addAction(UIAlertAction(title: "Update", style: .cancel) {_ in
    Distribute.notify(.update)
  })

  alertController.addAction(UIAlertAction(title: "Postpone", style: .default) {_ in
    Distribute.notify(.postpone)
  })

  // Show the alert controller.
  self.window?.rootViewController?.present(alertController, animated: true)
  return true;
}

如果返回 YES/true 上述方法,应用应使用以下 API 获取用户选择并向用户发送 SDK 消息。

// Depending on the user's choice, call notifyUpdateAction: with the right value.
[MSACDistribute notifyUpdateAction:MSACUpdateActionUpdate];
[MSACDistribute notifyUpdateAction:MSACUpdateActionPostpone];
// Depending on the user's choice, call notify() with the right value.
Distribute.notify(.update);
Distribute.notify(.postpone);

如果不调用上述方法,每当应用进入前台时, releaseAvailableWithDetails:-method 都会重复。

3.如果未找到更新,则执行代码

在 SDK 检查更新时,如果未发现比当前使用的版本更新的可用新版本,则会调用来自 MSACDistributeDelegate 委托的 distributeNoReleaseAvailable: 回调。 这样,就可以在此类方案中执行自定义代码。

下面是演示如何在未找到更新时显示警报 UI 的示例:

- (void)distributeNoReleaseAvailable:(MSACDistribute *)distribute {
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
                                                                 message:NSLocalizedString(@"No updates available", nil)
                                                          preferredStyle:UIAlertControllerStyleAlert];
  [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:nil]];
  [self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
  func distributeNoReleaseAvailable(_ distribute: Distribute) {
    let alert = UIAlertController(title: nil, message: "No updates available", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    self.window?.rootViewController?.present(alert, animated: true)
  }

在运行时启用或禁用 App Center Distribut

可以在运行时启用和禁用 App Center Distribute。 如果禁用此功能,SDK 不会提供任何应用内更新功能,但仍可以在 App Center 门户中使用分发服务。

[MSACDistribute setEnabled:NO];
Distribute.enabled = false

若要再次启用 App Center Distribute,请使用相同的 API,但作为参数传递 YES/true

[MSACDistribute setEnabled:YES];
Distribute.enabled = true

状态在应用程序启动时保留在设备的存储中。

注释

此方法只能在启动 Distribute 后使用。

检查是否启用了 App Center Distribute

还可以检查 App Center Distribute 是否已启用:

BOOL enabled = [MSACDistribute isEnabled];
var enabled = Distribute.enabled

注释

此方法应仅在 Distribute 启动后使用,在启动前,它将始终返回 false

不要在开发期间初始化 App Center Distribute

如果处于专用模式,App Center Distribute 将在应用程序启动时打开其 UI/浏览器。 虽然这对最终用户来说是预期行为,但对您来说,在应用程序开发阶段可能会造成影响。 不建议为配置DEBUG初始化Distribute

#if DEBUG
    [MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class]]];
#else
    [MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class], [MSACDistribute class]]];
#endif
#if DEBUG
    AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self])
#else
    AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self, Distribute.self])
#endif

在应用程序关闭更新之前立即执行清理

实现DistributeDelegate协议,并按照以下示例注册委托对象:

[MSACDistribute setDelegate:self];
Distribute.delegate = self;

distributeWillExitApp: 应用终止更新安装之前,将立即调用委托方法:

- (void)distributeWillExitApp:(MSACDistribute *)distribute {
  // Perform the required clean up here.
}
func distributeWillExitApp(_ distribute: Distribute) {
  // Perform the required clean up here.
}

应用内更新的工作原理是什么?

注释

若要使应用内更新正常工作,应从链接下载应用内部版本。 如果从 IDE 安装或手动安装,则它不起作用。

应用内更新功能的工作原理如下:

  1. 此功能仅适用于使用 App Center Distribute 服务分发的构建。 当附加调试器或启用 iOS 引导访问功能时,它不起作用。

  2. 集成 SDK 后,创建应用程序的发布版本,并将其上传到 App Center,分发组的用户将通过电子邮件收到新版本的通知。

  3. 每个用户在其电子邮件中打开链接时,应用程序将安装在其设备上。 至关重要的是,他们应该使用电子邮件中的链接来安装应用程序,因为 App Center Distribute 不支持从其他来源安装的应用程序的应用内更新(例如,从电子邮件附件下载应用程序)。 从链接下载应用程序时,SDK 会保存 Cookie 中的重要信息,以便以后检查更新,否则 SDK 没有该密钥信息。

  4. 如果应用程序将轨迹设置为专用,浏览器将打开以对用户进行身份验证并启用应用内更新。 只要身份验证信息保持有效,即使切换回公共模式,之后再返回私密模式,也不需要重新打开浏览器。 如果浏览器身份验证成功,用户会自动重定向回应用程序。 如果轨道是公共的(这是默认值),则下一步将直接执行。

    • 在 iOS 9 和 10 上,将在应用中打开一 SFSafariViewController 个实例以对用户进行身份验证。 身份验证成功后,它将自动关闭自身。
    • 在 iOS 11 上,用户体验类似于 iOS 9 和 10,但 iOS 11 将要求用户有权访问登录信息。 这是一个系统级对话框,无法对其进行自定义。 如果用户取消对话框,他们可以继续使用要测试的版本,但他们不会获得应用内更新。 下次启动应用时,系统会要求他们再次访问登录信息。
  5. 应用的新版本显示应用内更新对话框,要求用户更新应用程序(如果是):

    • 一个较高的值 CFBundleShortVersionString
    • 具有CFBundleShortVersionString的相等值,但CFBundleVersion的值更高。
    • 版本相同,但构建唯一标识符不同。

小窍门

如果第二次上传相同的 ipa,由于二进制文件相同,对话框 将不会 显示。 如果上传一个具有相同版本属性的新的构建,将会显示更新对话框。 原因是它是 不同的 二进制文件。

如何测试应用内更新?

需要将发布版本(使用 App Center SDK 的分发模块)上传到 App Center 门户,以测试应用内更新,每次增加版本号。

  1. 如果尚未创建应用,请在 App Center 门户中创建应用。
  2. 创建一个新的通讯组并将其命名,以便您可以识别它是用于测试应用程序内更新功能。
  3. 添加自己(或您希望包含在应用内更新测试中的所有人员)。 为此使用新的或丢弃的电子邮件地址,该地址不用于 App Center 上的该应用。 这可确保你的体验接近实际测试人员的体验。
  4. 创建包含 App Center Distribute 的应用的新内部版本,并包含以下设置逻辑。 如果该组是专用的,请不要忘记在开始使用 updateTrack 属性之前设置专用应用内更新跟踪。
  5. 单击门户中的“ 分发新版本 ”按钮并上传应用的生成。
  6. 上传完成后,单击“ 下一步 ”,然后选择创建的 通讯组 作为该应用分发 的目标
  7. 审查分发并将构建分发到应用内测试组。
  8. 该组中的人员将收到成为应用测试人员的邀请。 接受邀请后,他们可以从其移动设备从 App Center 门户下载应用。 安装应用内更新后,即可测试应用内更新。
  9. 更新您的应用的版本名称(CFBundleShortVersionString)。
  10. 生成应用的发布版本,并像在上一步中一样上传应用的新版本,并将其分发到之前创建的 通讯组 。 下次启动应用时,分发组的成员将会收到有关版本更新的提示。

小窍门

查看有关如何 利用 App Center Distribution 的信息,获取有关 通讯组 等的更多详细信息。虽然可以使用 App Center Distribut 分发新版应用而不添加任何代码,但将 App Center Distribute 添加到应用代码将导致测试人员和用户在获得应用内更新体验时获得更无缝的体验。

禁用将应用程序委托的方法调用转发到 App Center 服务

App Center SDK 使用方法调剂,通过将某些应用程序委托方法的调用转发给自身来改进其集成。 方法重排是一种在运行时更改方法实现的方法。 如果出于任何原因不想使用重排(例如,由于特定策略),可以按照以下步骤为所有 App Center 服务禁用此转发:

  1. 打开项目的 Info.plist 文件。
  2. 添加 AppCenterAppDelegateForwarderEnabled 键并将值设置为 0. 这会禁用所有 App Center 服务的应用程序委托转发。
  3. openURL 项目的 AppDelegate 文件中添加回调。
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {

  // Pass the url to MSACDistribute.
  return [MSACDistribute openURL:url];
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {

  // Pass the URL to App Center Distribute.
  return Distribute.open(url)
}