20

我在我的应用程序中设置了推送通知。我正在尝试确定我在该application:didRegisterForRemoteNotificationsWithDeviceToken:方法中从 APNS 收到的设备令牌是否来自沙盒或开发环境。如果我可以区分哪个环境初始化了令牌,我就可以告诉我的服务器向哪个环境发送推送通知。

我尝试使用DEBUG宏来确定这一点,但我看到了一些奇怪的行为,并且不相信它是 100% 正确的。

#ifdef DEBUG
BOOL isProd = YES;
#else
BOOL isProd = NO;
#endif

理想情况下,我可以检查aps-environment代码中的权利(值是开发或生产),但我不确定这是否可能。

确定您的应用程序是否与 APNS 沙箱或生产环境通信的正确方法是什么?我假设服务器首先需要知道这一点。如果这是假设不正确,请纠正我。

已编辑:Apple 关于Provider Communication with APNS的文档详细介绍了与沙箱和生产环境进行通信的区别。但是,该文档没有提供有关如何与注册令牌(从 iOS 客户端应用程序)和与服务器通信保持一致的信息。

4

5 回答 5

17

您可以阅读和检查嵌入式配置文件。

https://github.com/tcurdt/TCMobileProvision

这就是我所做的:

NSString *mobileprovisionPath = [[[NSBundle mainBundle] bundlePath]
        stringByAppendingPathComponent:@"embedded.mobileprovision"];
TCMobileProvision *mobileprovision = [[TCMobileProvision alloc] initWithData:[NSData dataWithContentsOfFile:mobileprovisionPath]];
NSDictionary *entitlements = mobileprovision.dict[@"Entitlements"];
NSString *apsEnvironment = entitlements[@"aps-environment"];
BOOL production = entitlements && apsEnvironment && [apsEnvironment isEqualToString:@"production"];
于 2014-05-28T10:44:36.567 回答
12

这是一个黑客,但它正在XCode 8使用Swift 3

我们基本上是打开embedded.mobileprovision文件,将其转换为字符串,然后检查表明应用程序正在使用开发应用程序环境的字符串。

func isDevelopmentEnvironment() -> Bool {
    guard let filePath = Bundle.main.path(forResource: "embedded", ofType:"mobileprovision") else {
        return false
    }
    do {
        let url = URL(fileURLWithPath: filePath)
        let data = try Data(contentsOf: url)
        guard let string = String(data: data, encoding: .ascii) else {
            return false
        }
        if string.contains("<key>aps-environment</key>\n\t\t<string>development</string>") {
            return true
        }
    } catch {}
    return false
}
于 2016-11-02T15:51:07.963 回答
4
  1. APNS 环境是根据与您的代码签名身份匹配的代码签名权利确定的(在此处发布好帖子) - 虽然识别您的构建配置可能有效,但如果您将该构建配置与不匹配的权利匹配,它也可能是错误的。

  2. 请记住这一点,使用 DEBUG 作为确定您的权利的方法应该有效(如果您发现 DEBUG 很棘手,您可以在“Apple LLVM ...”->“Other C Flags”->下添加自己的链接器标志“调试”)例如,添加 -DDEBUGGING 然后使用:

#ifdef DEBUGGING BOOL isProd = YES; #else BOOL isProd = NO; #endif

于 2012-04-13T23:43:07.077 回答
1

我想确保反序列化配置文件中的 plist,而不是搜索字符串。

import UIKit

public extension UIDevice {
    enum PushEnvironment: String {
        case unknown
        case development
        case production
    }

    var pushEnvironment: PushEnvironment {
        guard let provisioningProfile = try? provisioningProfile(),
              let entitlements = provisioningProfile["Entitlements"] as? [String: Any],
              let environment = entitlements["aps-environment"] as? String
        else {
            return .unknown
        }

        return PushEnvironment(rawValue: environment) ?? .unknown
    }

    // MARK: - Private

    private func provisioningProfile() throws -> [String: Any]? {
        guard let url = Bundle.main.url(forResource: "embedded", withExtension: "mobileprovision") else {
            return nil
        }

        let binaryString = try String(contentsOf: url, encoding: .isoLatin1)

        let scanner = Scanner(string: binaryString)
        guard scanner.scanUpToString("<plist") != nil, let plistString = scanner.scanUpToString("</plist>"),
              let data = (plistString + "</plist>").data(using: .isoLatin1)
        else {
            return nil
        }

        return try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any]
    }
}

您可以使用它来执行以下操作:

UIDevice.current.pushEnvironment == .production

当我告诉我的 API 关于我的设备时,我包括UIDevice.current.pushEnvironment.rawValue并且 API 可以使用适当的证书和网关来发送设备通知。

于 2021-11-09T21:11:41.640 回答
0

正如@tcurdt 的回答中提到的,确定是否使用沙箱的唯一安全方法是检查配置文件。这是使用 TCMobileProvision 的 Swift 代码:

func isAPNSandbox() -> Bool {
    if let mobileProvisionURL = NSBundle.mainBundle().URLForResource("embedded", withExtension: "mobileprovision"),
    let mobileProvisionData = NSData(contentsOfURL: mobileProvisionURL),
    let mobileProvision = TCMobileProvision(data: mobileProvisionData) {
        if let entitlements = mobileProvision.dict["Entitlements"],
        let apsEnvironment = entitlements["aps-environment"] as? String
        where apsEnvironment == "development" {
            return true
        }
    }

    return false
}

要安装 TCMobileProvision,请将其添加到您的 Podfile:

pod 'TCMobileProvision', :git => 'https://github.com/tcurdt/TCMobileProvision.git'
于 2015-11-05T13:32:39.567 回答