Changes to iOS 13 Push Notification Device Token

Back in October 2019, Apple changed the way they were getting device tokens for remote push notifications. Is there any progress on updating the engine code (IOSAppDelegate.cpp) to account for these changes?

I’m not the greatest at converting the objective-c to C++ (let alone UE4 C++), but it appears the new method should be this:

+ (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];
}

Whereas the current code is this:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
	if (FApp::IsUnattended())
	{
		return;
	}

	TArray<uint8> Token;
	Token.AddUninitialized([deviceToken length]);
	memcpy(Token.GetData(), [deviceToken bytes], [deviceToken length]);

	const char *data = (const char*)([deviceToken bytes]);
	NSMutableString *token = [NSMutableString string];

	for (NSUInteger i = 0; i < [deviceToken length]; i++) {
		[token appendFormat : @"%02.2hhX", data[i]];
	}

	UE_LOG(LogTemp, Display, TEXT("Device Token: %s"), *FString(token));

    FFunctionGraphTask::CreateAndDispatchWhenReady([Token]()
    {
		FCoreDelegates::ApplicationRegisteredForRemoteNotificationsDelegate.Broadcast(Token);
    }, TStatId(), NULL, ENamedThreads::GameThread);
}

If anyone has already updated the source and would like to share their changes, that’d be super helpful. Our game is already in production, and the most recent change for iOS kind of screwed our push notification updates we were planning on implementing.

Thanks in advance.

Ok, so I’ve made some head way in figuring out what might be going on, so I’m updating this with that information in hopes it’ll help come to a resolution.

With the current code above, I don’t think that actually needs to be changed as UE4 is not using the description for pulling a device token; not using this is following the guidelines of iOS 13 change that broke things for people using the description.

I did however, need to add this code block to line 1156 of Engine\Source\Runtime\Core\Private\IOSPlatformMisc.cpp as suggested in UE-67087 here: https://unreal-engine-issues.herokuapp.com/issue/UE-67087

if (granted)
{
	UIApplication* application = [UIApplication sharedApplication];
	[application registerForRemoteNotifications];
}

Upon doing so, I was actually able to get some output on the iOS side of things from the byte array that is output from binding to the ApplicationRegisteredForRemoteNotificationsDelegate Event in blueprints.

Upon looking through my device logs, I noticed that a correctly formatted device token was being returned from the UE_LOG call (line 19 in my original post of current code); however, because the ApplicationRegisteredForRemoteNotificationsDelegate Event returns a byte array and not an FString, something is happening when converting the bytes array back to FString. Upon conversion I get a junk string value.

Here’s the log pertaining to device token:

[2020.06.17-04.10.44:291][399]LogBlueprintUserMessages: [GlobalGameInstance_C_2147482608] Successfully Linked new iOS device
[2020.06.17-04.10.44:291][399]LogBlueprintUserMessages: [GlobalGameInstance_C_2147482608] Registering Remote Push Notifications...
[2020.06.17-04.10.44:307][400]LogTemp: Display: Device Token: D8XXXXX070B7D6E8F8D04BBC82D834CC99CFF886807912F1FDE8EF2AAA773186
[2020.06.17-04.10.44:307][400]LogBlueprintUserMessages: [GlobalGameInstance_C_2147482608] In Push Notification Delegate...
[2020.06.17-04.10.44:307][400]LogBlueprintUserMessages: [GlobalGameInstance_C_2147482608] Device Token: ???Pp?????K???4??????y????*?w1?

This is the code I’m using to convert the byte array to string, and maybe this is where it’s getting jumbled; however, the same helper function I wrote to do this, works properly in converting the Android device token properly binding to the same delegate.

FString UHuliHelper::BytesToStringFixed(const TArray<uint8> &InByteArray)
{
	//Create string from byte array
	const std::string cstr(reinterpret_cast<const char*>(InByteArray.GetData()), InByteArray.Num());
	return FString(cstr.c_str());
}

Any help would be greatly appreciated, thanks!