Firebase Cloud Messaging(FCM)如何切换Apple Push Notification服务(APNs)的环境?

4
在苹果推送通知服务(APNs)中,服务器端开发人员必须选择环境类型(沙盒或生产环境),作为HTTP/2 URL的一部分(api.sandbox.push.apple.com或api.push.apple.com)。[1]
另一方面,在Firebase云消息传递(FCM)上使用APNs时,似乎没有明确的界面来指定环境类型。[2]
因此,我猜测FCM在内部决定环境类型,但我不知道它是如何检测环境类型的。
是否有人了解这方面的信息?任何见解都会有帮助。谢谢!

这也是我的结论。也许当令牌被注册时,Firebase SDK会检测构建模式!调试或发布。或者也许有一些模式可以区分生产和开发令牌。 - hasan
非常感谢您的回复!嗯...您知道是否有任何关于它的文档或推理吗? - Yuki Hashimoto
没有,我没费心,因为一切都正常工作 :D 所以继续前进。哈哈 - hasan
3个回答

5

一些先决条件信息

  • 当应用程序在Xcode中以调试、发布或配置文件的方式构建和运行,或者通过开发方法分发时,始终使用沙盒环境。
  • 生产环境用于通过App Store Connect(App Store和TestFlight)Ad Hoc企业级方法分发应用程序。有关更多信息,请参见"Distributing Your App for Beta Testing and Releases"
  • 要了解使用的分发模式/APNs环境,必须阅读预配文件。在iOS、watchOS和tvOS上,它是embedded.mobileprovision,而在macOS或Catalyst上,它是embedded.provisionprofile。您无法读取App.entitlements,因为该文件并不总是可用。相反,embedded.mobileprovision包含一个字典(以XML格式)。这是我从测试应用程序中提取的此文件的示例。它包含,除其他外:
<key>Entitlements</key>
<dict>
<key>aps-environment</key>
<string>development</string>
...

如果您自己生成(归档Xcode项目),您可以查看xcarchive的包内容(/Users/username/Library/Developer/Xcode/Archives/2021-08-28/projectName\ 28-08-2021,\ 08.17.xcarchive/Products/Applications/projectName.app/embedded.mobileprovision),并且在finder预览中显示得很好。Firebase iOS SDK中也有一条注释:
 *  @param type  The type of APNs token. Debug builds should use
 *  FIRMessagingAPNSTokenTypeSandbox. Alternatively, you can supply
 *  FIRMessagingAPNSTokenTypeUnknown to have the type automatically
 *  detected based on your provisioning profile.

Firebase的解决方案

您可以阅读FIRMessagingTokenManager.m,或阅读我在不同文件中的分析:

Firebase iOS SDK中,如果您未传递类型(沙盒/生产)或明确传递FIRMessagingAPNSTokenTypeUnknown,则会运行此代码:

  if (type == FIRMessagingAPNSTokenTypeUnknown) {
    isSandboxApp = FIRMessagingIsSandboxApp();
  }

这是

BOOL FIRMessagingIsSandboxApp(void) {
  static BOOL isSandboxApp = YES;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    isSandboxApp = !FIRMessagingIsProductionApp();
  });
  return isSandboxApp;
}

FIRMessagingIsProductionApp 是一个长达119行的方法。它是用来做什么的?它几乎总是默认为生产应用程序,有很多Firebase特定的配置逻辑,并检查如果在iOS模拟器上运行,则是否为生产环境,如果应用程序是通过AppStore或TestFlight交付的。

从根本上讲,它会检查 embedded.provisionprofileembedded.mobileprovision(这就是生成 plistMap 的方式):

// plistMap is loaded from the provisioning profile in a multi step process.
NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey];

  if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) {
    return NO;
  }

在配置文件中,他们引用以下密钥:

#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment";
#else
static NSString *const kEntitlementsAPSEnvironmentKey =
    @"Entitlements.com.apple.developer.aps-environment";
#endif
static NSString *const kAPSEnvironmentDevelopmentValue = @"development";

如果您想查看配置文件的读取方式,请查看源文件。
  • 创建完整的配置文件路径
  • 从文件路径加载数据
  • 清理数据(配置文件包含0,会“停止”ASCII解析器,或者大于127的值,是无效的。)
  • 将数据转换为字符串
  • 使用{{link3:NSScanner扫描字符串}}。他们这样做是因为配置文件包含更多非xml/非plist结构。看看示例文件
  • 将此字符串转换回数据。
  • 使用NSPropertyListSerialization将此数据转换为字典
  • 查找ProvisionedDevices键,如果存在,则为开发配置文件。
  • 从字典中获取环境,使用kEntitlementsAPSEnvironmentKey

Firebase服务器如何知道使用哪个端点?

最后,一旦Firebase iOS SDK知道设备(和APNs设备令牌)正在生产/开发中运行,它可以告诉APNs提供者(与APNs连接的服务器)使用正确的端点,即api.push.apple.com:443api.sandbox.push.apple.com:443,又名api.development.push.apple.com:443(它只是指向沙盒的CNAME)。这个isProductionisSandbox布尔值可能会与APNs设备令牌一起存储在Firebase数据库中。


1

1
找到了有关 Firebase 的文档。链接 - Prasad Parab

0
我们用于发送通知的 FCM 令牌是由 SDK 使用多个参数生成的。它包含有关实际 APNS 设备令牌、项目 ID、Firebase 上的项目 URL 端点、应用程序包标识符等信息(如果您尝试使用从不同 Firebase 配置生成的其他令牌,则会收到无效令牌错误)。显然,FCM 令牌还考虑了用于编译应用程序的环境(DEBUG/RELEASE)。使用这些信息,Firebase 应该能够使用相应的 APNS 网关。

谢谢,Parasad!你有关于它的任何文档链接吗? - Yuki Hashimoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接