2012-04-13 7 views
15

Ich habe Push-Benachrichtigungen in meiner App eingerichtet. Ich versuche festzustellen, ob das Geräte-Token, das ich von APNS in der application:didRegisterForRemoteNotificationsWithDeviceToken:-Methode erhalten habe, aus der Sandbox oder der Entwicklungsumgebung stammt. Wenn ich unterscheiden kann, in welcher Umgebung das Token initialisiert wurde, kann ich meinem Server mitteilen, an welche Umgebung die Push-Benachrichtigung gesendet werden soll.Ermitteln, ob die App mit der Sandbox APNS oder der Produktionsumgebung kommuniziert

Ich habe versucht, mit dem DEBUG Makro, um dies zu bestimmen, aber ich habe ein seltsames Verhalten mit diesem gesehen und nicht darauf vertrauen, dass es 100% korrekt ist.

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

Idealerweise würde ich in der Lage sein, die aps-environment Berechtigung (Wert Entwicklung oder Produktion) in Code zu untersuchen, aber ich bin nicht sicher, ob dies überhaupt möglich ist.

Wie können Sie feststellen, ob Ihre App mit der APNS-Sandbox oder Produktionsumgebungen kommuniziert? Ich gehe davon aus, dass der Server dies in erster Linie wissen muss. Bitte korrigieren Sie mich, wenn diese Annahme falsch ist.

Bearbeitet: Apples Dokumentation auf Provider Communication with APNS Details der Unterschied zwischen der Kommunikation mit der Sandbox und Produktion. Die Dokumentation enthält jedoch keine Informationen darüber, wie die Registrierung des Tokens (von der iOS-Client-App) und die Kommunikation mit dem Server konsistent sein sollen.

Antwort

14

Sie können das eingebettete Provisioning-Profil lesen und überprüfen.

https://github.com/tcurdt/TCMobileProvision

Das ist, was ich tue:

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"]; 
+0

Die Bibliothek ist ein wenig veraltet, aber sie hat gut funktioniert. Umgebung '(ersetzen Sie' "get-task-allow" 'mit' "aps-environment" 'in @tcurdts Beispiel, und vergleichen Sie es nicht als bool) –

+0

@AlbertBori können Sie bitte ein Problem auf, was ist veraltet? – tcurdt

+0

Sicher Sache! Hier gehts: https://github.com/tcurdt/TCMobileProvision/issues/1 –

4
  1. Die APNS Umgebung wird nach den Codezeichen Entitlements Ihr-Code Zeichen Identität (guter Beitrag here) passend bestimmt - während die Build-Konfiguration identifiziert arbeiten kann, ist es auch falsch sein kann, wenn Sie diese Build-Konfiguration angepasst haben mit einem nicht übereinstimmenden Anspruch.

  2. In diesem Sinne sollte die Verwendung von DEBUG als Mittel zur Ermittlung Ihrer Berechtigungen funktionieren (wenn Sie DEBUG als knifflig empfinden, können Sie unter "Apple LLVM ..." -> "Andere" ein eigenes Linker-Flag hinzufügen C Flags“-> "Debug") zum Beispiel -DDEBUGGING hinzufügen und dann verwenden:

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

+0

Danke für die Antwort, @Wiz. Ich habe am Ende einen Boolean in der Konfiguration plist Datei verwendet. Wie Sie bereits erwähnt haben, ist der einzige Haken, dass diese Konfigurationseinstellung mit der Code-Signatur übereinstimmen muss, die sich in der Projektdatei befindet. Es ist unerwünscht, aber die beste verfügbare Lösung. – goldierox

+0

Einverstanden. Apple könnte einfach eine API bereitstellen, die Ihnen sagt, was die aktuelle Berechtigung ist - dann können Sie die Produktion einstellen oder Sandbox-Token an Ihren Sandbox-Server weiterleiten ... –

0

Wie in @ tcurdt Antwort erwähnt, ist der einzig sichere Weg, um zu bestimmen, ob die Sandbox verwenden oder nicht, ist die Provisioning-Datei zu überprüfen. Hier ist der Swift-Code, mit TCMobileProvision:

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 
} 

Um TCMobileProvision zu installieren, fügen Sie diese zu Ihrer Podfile:

pod 'TCMobileProvision', :git => 'https://github.com/tcurdt/TCMobileProvision.git' 
+0

Phatmann, danke für den Swift-Code. Ich bin neugierig, wenn Sie einen Grund haben, einen booleschen Zustand von Sandbox zu überprüfen und nicht wahr, wenn auf Produktion? Was ich fand, war, dass, wenn ich einen lokalen Build von xCode ausführe, es beim Versuch fehlschlägt, 'mobileprovision' zu laden, was eine Rückkehr von falschem verursacht (anzeigend, dass es NICHT in der Sandbox ist). Wenn ich jedoch eine von Sandbox bereitgestellte Archivdatei erstelle, die die Datei mobileprovision erfolgreich lädt, wird angezeigt, dass es sich um eine Sandbox-Erstellung handelt. In diesem Fall scheint es notwendig zu sein, zu testen, ob "Produktion" erfolgreich gefunden wurde. – KeithB

+0

@KeithB scheint der beste Weg zu sein, eine Enum mit 'sandbox',' production' und 'unspecified' zurückzugeben. Fühlen Sie sich frei, den Code entsprechend zu bearbeiten. – phatmann

4

Dies ist ein Hack, aber seine Arbeit an XCode 8 mit Swift 3

Wir Im Grunde die embedded.mobileprovision Datei zu öffnen, wandelt es in eine Zeichenfolge und dann nach einer Zeichenfolge, die die App verwenden würde die Entwicklung aps-Umgebung.

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 
}