20

アプリにプッシュ通知を設定しています。application:didRegisterForRemoteNotificationsWithDeviceToken:メソッドでAPNSから受け取ったデバイストークンがサンドボックスからのものか、開発環境からのものかを判断しようとしています。どの環境がトークンを初期化したかを区別できれば、プッシュ通知を送信する環境をサーバーに伝えることができます。

マクロを使用してこれを判別しようとしましたDEBUGが、これで奇妙な動作が見られ、100%正しいとは信じられません。

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

理想的にはaps-environment、コードで資格(値は開発または本番)を調べることができますが、これが可能かどうかはわかりません。

アプリがAPNSサンドボックスと本番環境のどちらと通信しているかを判断する適切な方法は何ですか?そもそもサーバーがこれを知る必要があると思います。これが仮定が正しくない場合は、私を訂正してください。

編集: APNSとのプロバイダー通信に関するAppleのドキュメントでは、サンドボックスとの通信と本番環境との通信の違いについて詳しく説明しています。ただし、ドキュメントには、(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 8Swift 3

基本的に、embedded.mobileprovisionファイルを開いて文字列に変換し、アプリが開発aps-environmentを使用していることを示す文字列をチェックします。

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環境は、コードサインIDに一致するコードサインエンタイトルメントに従って決定されます(ここに良い投稿があります)-ビルド構成の識別は機能する可能性がありますが、そのビルド構成を不一致のエンタイトルメントと一致させた場合はfalseになる可能性もあります。

  2. そのことを念頭に置いて、資格を決定する手段としてDEBUGを使用すると、機能するはずです(DEBUGが扱いにくい場合は、「AppleLLVM...」->「その他のCフラグ」->の下に独自のリンカーフラグを追加できます。 「デバッグ」)たとえば、-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 に答える