Uzyskaj token urządzenia do powiadomień push

84

Pracuję nad powiadomieniami push. Napisałem następujący kod do pobierania tokena urządzenia.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    // Override point for customization after application launch.

    // Add the view controller's view to the window and display.
    [self.window addSubview:viewController.view];
    [self.window makeKeyAndVisible];

    NSLog(@"Registering for push notifications...");    
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

    return YES;
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
    NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
    NSLog(@"This is device token%@", deviceToken);
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
    NSString *str = [NSString stringWithFormat: @"Error: %@", err];
    NSLog(@"Error %@",err);    
}

Mogę pomyślnie uruchomić aplikację na urządzeniu, ale nie mogę uzyskać identyfikatora urządzenia na konsoli.

Nie mam problemów z profilami certyfikacji i obsługi administracyjnej.

jagzzz
źródło
Czy wykonałeś wszystkie kroki ? Jeśli nie masz żadnego problemu z certyfikacją i udostępnianiem, a także kodem, musisz popełnić mały błąd. Na przykład ... powiedz mi, czy uruchamiasz aplikację na prawdziwym urządzeniu, podłączając to samo do swojego systemu? Czy zauważasz również, czy otrzymujesz token urządzenia w dzienniku konsoli, czy nie? Czy włączyłeś powiadomienia push na iPhonie ?
Sarah,
Nie mogę uzyskać tokena urządzenia w dzienniku konsoli.
jagzzz
Uruchamiam aplikację na prawdziwym urządzeniu bez żadnego błędu.
jagzzz
Czy włączyłeś APNS, jak pokazano w linku na iPhonie?
Sarah,
tak, włączyłem APNS ... ale token urządzenia nie jest w stanie pobrać na cosole
jagzzz

Odpowiedzi:

163

UWAGA: Poniższe rozwiązanie nie działa już na urządzeniach z systemem iOS 13+ - zwróci dane śmieci .

Zamiast tego użyj następującego kodu:

+ (NSString *)hexadecimalStringFromData:(NSData *)data
{
  NSUInteger dataLength = data.length;
  if (dataLength == 0) {
    return nil;
  }

  const unsigned char *dataBuffer = (const unsigned char *)data.bytes;
  NSMutableString *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];
  for (int i = 0; i < dataLength; ++i) {
    [hexString appendFormat:@"%02x", dataBuffer[i]];
  }
  return [hexString copy];
}

Rozwiązanie, które działało przed iOS 13:

Cel C

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 
{
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"this will return '32 bytes' in iOS 13+ rather than the token", token);
} 

Swift 3.0

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    let tokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print("this will return '32 bytes' in iOS 13+ rather than the token \(tokenString)")
}
Wasif Saood
źródło
4
Następnie sprawdź swój profil obsługi administracyjnej. Powinien to być identyfikator aplikacji, za pomocą którego utworzyłeś certyfikat ssl do powiadomień push.
Wasif Saood
1
musisz dodać kod do pliku AppDelegate @jagzzz
codercat
2
Dla zainteresowanych przykładem kodu napisanym w języku Swift: gist.github.com/sawapi/a7cee65e4ad95578044d
Benjamin
3
Ostrożnie, używanie właściwości „description” już nie działa: stackoverflow.com/questions/39495391/ ...
hariseldon78
1
@codester Przesłałem moją kompilację przy użyciu Xcode 10.3 i jest ona dostępna. Zgodnie z Twoim oświadczeniem, metoda Objective C będzie zepsuta dalej XCode 11, ale to, co widzę w naszej bazie danych, pokazuje długość danych zamiast prawidłowego ciągu tokenu apns. Więc chcę tylko wiedzieć, czy to zależy od wersji Xcode czy wersji iOS (tj. 13. *)?
pradip sutariya
13

Aby uzyskać urządzenie tokenowe, możesz wykonać kilka czynności :

1) Włącz APNS (usługę Apple Push Notification Service) zarówno dla certyfikacji programisty, jak i dla dystrybucji certyfikacji, a następnie ponownie pobierz te dwa pliki.

2) Pobierz ponownie plik obsługi administracyjnej programistów i plik obsługi administracyjnej dystrybucji.

3) W interfejsie Xcode: konfigurowanie obsługi administracyjnej dla PROJEKTU i CELÓW z obsługą dwóch plików jest do pobrania.

4) Na koniec musisz dodać poniższy kod w pliku AppDelegate, aby uzyskać Token Device (uwaga: uruchom aplikację na prawdziwym urządzeniu).

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
     [self.window addSubview:viewController.view];
     [self.window makeKeyAndVisible];

     NSLog(@"Registering for push notifications...");    
     [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
 (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
     return YES;
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
     NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
     NSLog(@"%@", str);
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
     NSString *str = [NSString stringWithFormat: @"Error: %@", err];
     NSLog(@"%@",str);
}
Bkillnest
źródło
11

Korzystanie z descriptionwielu z tych odpowiedzi jest złym podejściem - nawet jeśli zaczniesz działać, zepsuje się w iOS 13+.

Zamiast tego powinieneś upewnić się, że używasz rzeczywistych danych binarnych, a nie tylko ich opisu. Andrey Gagan całkiem dobrze poradził sobie z rozwiązaniem Objective C, ale na szczęście jest to znacznie prostsze w szybkim:

Swift 4.2 działa w iOS 13+

// credit to NSHipster (see link above)
// format specifier produces a zero-padded, 2-digit hexadecimal representation
let deviceTokenString = deviceToken.map { String(format: "%02x", $0) }.joined()
Chris Stamper
źródło
7

Objective C for iOS 13+ , dzięki odpowiedzi Wasif Saood

Skopiuj i wklej poniższy kod do AppDelegate.m, aby wydrukować token APN urządzenia.

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  NSUInteger dataLength = deviceToken.length;
  if (dataLength == 0) {
    return;
  }
  const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes;
  NSMutableString *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];
  for (int i = 0; i < dataLength; ++i) {
    [hexString appendFormat:@"%02x", dataBuffer[i]];
  }
  NSLog(@"APN token:%@", hexString);
}
Jake Cronin
źródło
5

Poniższy kod służy do pobierania tokenu urządzenia.

    // Prepare the Device Token for Registration (remove spaces and < >)
    NSString *devToken = [[[[deviceToken description] 
                            stringByReplacingOccurrencesOfString:@"<"withString:@""] 
                           stringByReplacingOccurrencesOfString:@">" withString:@""] 
                          stringByReplacingOccurrencesOfString: @" " withString: @""];


    NSString *str = [NSString 
                     stringWithFormat:@"Device Token=%@",devToken];
    UIAlertView *alertCtr = [[[UIAlertView alloc] initWithTitle:@"Token is " message:devToken delegate:self cancelButtonTitle:nil otherButtonTitles: nil] autorelease];
    [alertCtr show];
    NSLog(@"device token - %@",str);
Nimit Parekh
źródło
3
To nigdy nie było właściwe rozwiązanie. Nigdy nie opieraj niczego na description.
rmaddy,
5

I szybka wersja odpowiedzi Wasif:

Swift 2.x

var token = deviceToken.description.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<>"))
token = token.stringByReplacingOccurrencesOfString(" ", withString: "")
print("Token is \(token)")

Aktualizacja dla Swift 3

let deviceTokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
Antoine
źródło
Nigdy nie używaj descriptionna danych binarnych (zobacz inną odpowiedź)
chris stamper
4

Jeśli nadal nie otrzymujesz tokena urządzenia, spróbuj wprowadzić następujący kod, aby zarejestrować urządzenie na potrzeby powiadomień push.

Będzie również działać na ios8 lub więcej.

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000

    if ([UIApplication respondsToSelector:@selector(registerUserNotificationSettings:)]) {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound
                                                                                 categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         UIRemoteNotificationTypeBadge |
         UIRemoteNotificationTypeAlert |
         UIRemoteNotificationTypeSound];

    }
#else
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     UIRemoteNotificationTypeBadge |
     UIRemoteNotificationTypeAlert |
     UIRemoteNotificationTypeSound];

#endif
Nilesh
źródło
4

Począwszy od iOS 13 Apple zmienił [deviceToken description]wyjście. Teraz jest tak, {length=32,bytes=0x0b8823aec3460e1724e795cba45d22e8...af8c09f971d0dabc}co jest nieprawidłowe dla tokena urządzenia.

Proponuję użyć tego fragmentu kodu, aby rozwiązać problem:

+ (NSString *)stringFromDeviceToken:(NSData *)deviceToken {
    NSUInteger length = deviceToken.length;
    if (length == 0) {
        return nil;
    }
    const unsigned char *buffer = deviceToken.bytes;
    NSMutableString *hexString  = [NSMutableString stringWithCapacity:(length * 2)];
    for (int i = 0; i < length; ++i) {
        [hexString appendFormat:@"%02x", buffer[i]];
    }
    return [hexString copy];
}

Będzie działać na iOS13 i niższych wersjach.

Andrey Gagan
źródło
1
FYI - każda odpowiedź, której kiedykolwiek użyłem, descriptionbyła zawsze błędna. A to tylko jedno możliwe rozwiązanie konwersji tokena na ciąg. Dużo prostszym rozwiązaniem jest konwersja NSDatado NSStringstandardowego kodowania base64.
rmaddy,
1

Zdobądź token urządzenia w Swift 3

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})

    print("Device token: \(deviceTokenString)")

}
Sedat Y
źródło
1

W Twojej AppDelegate, w didRegisterForRemoteNotificationsWithDeviceTokenmetodzie:

Zaktualizowano dla Swift:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("\(deviceToken.reduce("") { $0 + String(format: "%02.2hhx", arguments: [$1]) })")
}
vfn
źródło
0

Swift 4 To działa dla mnie:

Krok 1 do CELÓW Kliknij opcję dodawania funkcji i wybierz Powiadomienia push

Krok 2 w AppDelegate.swift dodaj następujący kod:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound]) { (didAllow, error) in
            
        }
        UIApplication.shared.registerForRemoteNotifications()
        
        return true
    }
    
    //Get device token
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    {
        let tokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
        
        print("The token: \(tokenString)")
    }
James Ryan
źródło
-1

W ustawieniach kompilacji ustaw profil udostępniania podpisywania kodu, jeśli masz certyfikat APN Enable, na pewno otrzymasz identyfikator tokena. i usuń

Profil zaopatrzenia: automatyczny

i ustaw na

Profil obsługi: Twój certyfikat profilu obsługi.

kalpesh
źródło
-1
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
        }
    let token = tokenParts.joined()

    print("Token\(token)")
}
Amit Gupta
źródło
-4

Aby uzyskać token urządzenia, użyj następującego kodu, ale możesz uzyskać token urządzenia tylko za pomocą urządzenia fizycznego. Jeśli masz obowiązek wysłania tokena urządzenia to korzystając z symulatora możesz postawić poniższy warunek.

  if(!(TARGET_IPHONE_SIMULATOR))
    {
        [infoDict setValue:[[NSUserDefaults standardUserDefaults] valueForKey:@"DeviceToken"] forKey:@"device_id"];
    }
    else
    {
        [infoDict setValue:@"e79c2b66222a956ce04625b22e3cad3a63e91f34b1a21213a458fadb2b459385" forKey:@"device_id"];
    }



- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
    NSLog(@"My token is: %@", deviceToken);
    NSString * deviceTokenString = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""]   stringByReplacingOccurrencesOfString: @" " withString: @""];
    NSLog(@"the generated device token string is : %@",deviceTokenString);
    [[NSUserDefaults standardUserDefaults] setObject:deviceTokenString forKey:@"DeviceToken"];
}
Yash
źródło