Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not compatible with iOS 13 background push notifications #909

Open
AlexBrownShi opened this issue Sep 19, 2019 · 14 comments
Open

Not compatible with iOS 13 background push notifications #909

AlexBrownShi opened this issue Sep 19, 2019 · 14 comments

Comments

@AlexBrownShi
Copy link

AlexBrownShi commented Sep 19, 2019

What version of PushSharp are you using?

4.0.10.0

Describe your issue:

Background push notifications are not received by iOS 13 devices properly.

What are the steps required to reproduce this issue?

Send a background push notification by specifying: aps-content-available:1 and payload.

Please provide any Exception Stack Traces

No exception. Notification sends properly, but never received as a background notification. Possible it is received as a foreground notification, not sure.

See the following in iOS Notifications documentation:
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns

Excerpt on Headers:
apns-push-type :
(Required when delivering notifications to devices running iOS 13 and later, or watchOS 6 and later. Ignored on earlier system versions.) The type of the notification. The value of this header is alert or background. Specify alert when the delivery of your notification displays an alert, plays a sound, or badges your app's icon. Specify background for silent notifications that do not interact with the user. The value of this header must accurately reflect the contents of your notification's payload. If there is a mismatch, or if the header is missing on required systems, APNs may delay the delivery of the notification or drop it altogether. For information about configuring notification alerts, see Generating a Remote Notification. For more information about sending background notifications, see Pushing Background Updates to Your App.

I only see headers being used when using HttpTwo. If that is working, the fix may not be too complex.

@margaritamejia
Copy link

+1

@Alexander-Alekseev
Copy link

Alexander-Alekseev commented Oct 2, 2019

Hello @Redth,

Seems like you are very busy with other projects, but this issues looks very critical. Maybe you can find several minutes/hours to look at this problem? Or at least maybe you can give us an advice how to fix/workaround this, please?

I found that you generate request's headers as list of bytes, for example:

builder.Add (0x01); // Device Token ID
builder.AddRange (BitConverter.GetBytes (IPAddress.HostToNetworkOrder (Convert.ToInt16 (deviceToken.Length))));
builder.AddRange (deviceToken);
// 2 - Payload
var payload = Encoding.UTF8.GetBytes (ToString ());
if (payload.Length > MAX_PAYLOAD_SIZE)
throw new NotificationException ("Payload too large (must be " + MAX_PAYLOAD_SIZE + " bytes or smaller", this);
builder.Add (0x02); // Payload ID
builder.AddRange (BitConverter.GetBytes (IPAddress.HostToNetworkOrder (Convert.ToInt16 (payload.Length))));
builder.AddRange (payload);
// 3 - Identifier
builder.Add (0x03);
builder.AddRange (BitConverter.GetBytes (IPAddress.HostToNetworkOrder ((Int16)4)));
builder.AddRange (BitConverter.GetBytes (IPAddress.HostToNetworkOrder (Identifier)));

How do you know that device token is 0x01, payload is 0x02, identifier is 0x03 and so on?
How can we put the pair of values apns-push-type: alert in bytes list in a such format?

@sunnyy02
Copy link

sunnyy02 commented Oct 2, 2019

The 0x01 and 0x02 is according to the "Provider API" schema from Apple.
It does not have the headers or the aps-push-type, as the provider api is a legacy API, not being updated or supported.
I am facing the same issue, and decided to move to .Net core to consume the new APNS api with http/2.
https://medium.com/@sunnysun_5694/send-push-notification-from-net-service-to-ios-devices-using-pushsharp-7a7bf9f7fb36

@Alexander-Alekseev
Copy link

Alexander-Alekseev commented Oct 2, 2019

Hey @AlexBrownShi, @margaritamejia, @ManeyYamazin,

I was able to send pushes to my app wihout changes in PushSharp (for now, at least).
Check your iOS application ((void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken method, for example). iOS13 generates device token in a new format.

For example,
old format:

<124686a5 556a72ca d808f572 00c323b9 3eff9285 92445590 3225757d b83997ba>

new format:

{ length = 32, bytes = 0xd3d997af 967d1f43 b405374a 13394d2f ... 28f10282 14af515f }

So wrong push token (device token) was the reason why I was not able to send push to my app.

You can use the following code to 'repair' new token format:

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

For more details read this.


P.S.: it should be mentioned that I develop iOS app only; watchOS still needs the solution.

@kirtisagar
Copy link

@Alexander-Alekseev I don't think we can use the lagacy format to send silent notification to iOS 13 devices. as per Apple we need to add new header apns-push-type

Check this out, PushSharp uses lagacy headers and you cannot add a new header apns-push-type
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/BinaryProviderAPI.html#//apple_ref/doc/uid/TP40008194-CH13-SW1

I think the solution is use HTTP/2 :
https://github.com/andrei-m-code/net-core-push-notifications

@juliancorrea
Copy link

Hey @AlexBrownShi, @margaritamejia, @ManeyYamazin,

I was able to send pushes to my app wihout changes in PushSharp (for now, at least).
Check your iOS application ((void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken method, for example). iOS13 generates device token in a new format.

For example,
old format:

<124686a5 556a72ca d808f572 00c323b9 3eff9285 92445590 3225757d b83997ba>

new format:

{ length = 32, bytes = 0xd3d997af 967d1f43 b405374a 13394d2f ... 28f10282 14af515f }

So wrong push token (device token) was the reason why I was not able to send push to my app.

You can use the following code to 'repair' new token format:

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

For more details read this.

P.S.: it should be mentioned that I develop iOS app only; watchOS still needs the solution.

This doesnt work. I tested in PushSharp 2.2.1.0.

The new header apns-push-type is required for IOS 13:

apns-push-type | (Required for watchOS 6 and later; recommended for macOS, iOS, tvOS, and iPadOS) The value of this header must accurately reflect the contents of your notification’s payload. If there is a mismatch, or if the header is missing on required systems, APNs may return an error, delay the delivery of the notification, or drop it altogether.

Documentation at: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns

@Eternal21
Copy link

@Alexander-Alekseev I don't think we can use the lagacy format to send silent notification to iOS 13 devices. as per Apple we need to add new header apns-push-type

Check this out, PushSharp uses lagacy headers and you cannot add a new header apns-push-type
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/BinaryProviderAPI.html#//apple_ref/doc/uid/TP40008194-CH13-SW1

I think the solution is use HTTP/2 :
https://github.com/andrei-m-code/net-core-push-notifications

Using linked HTTP/2 solution (Core Push library) works, with one caveat. You need to use either Windows 10 or Windows Server 2016 or later. Otherwise you run into cipher issues with Apple server.

@juliancorrea
Copy link

It seems there is no solution for Binary Provider API, cause there is no section for apns-push-type in the documentation:https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/LegacyNotificationFormat.html#//apple_ref/doc/uid/TP40008194-CH14-SW1.

Am I wrong?

@Alexander-Alekseev
Copy link

@juliancorrea,

This doesnt work. I tested in PushSharp 2.2.1.0.

Well, it's pretty old. I was using v4.0.10.

The new header apns-push-type is required for IOS 13:

Wrong. apns-push-type required for watshOS 6, but recommended for iOS. Anyway, it could be required for iOS once.

It seems there is no solution for Binary Provider API... Am I wrong?

You are right, there is no solution for Binary Provider API.


For all of you who reads this topic: if you already have your own server in production which is huge and written in .NET Framework 4.5+ there is a solution without moving to .NET Core and HTTP/2. The solution is to use FCM and this sender - https://github.com/andrei-m-code/net-core-push-notifications/blob/master/CorePush/Google/FcmSender.cs (though original project was written in .NET Core, this sender perfectly works with .NET FW 4.5.1 and I think it works even with 4.5).
Moving to FCM won't be painful especially if you already have Android version of your app.

As a result: the pointed sender (which is very small!) replaces the whole PushSharp (if you are interesting in iOS and/or Android only).

@ArkaitzOB
Copy link

Then PushSharp.Google.GcmServiceBroker should also be able to send notifications to iOS devices, shouldn't it?

@Alexander-Alekseev
Copy link

@ArkaitzOB, I didn't think about it, but yeah, it should (of course if you change GCM address to FCM). Anyway, in our server we decided to move from PushSharp as it's no longer maintainable.

@ArkaitzOB
Copy link

Indeed, it's a pity as the OnNotificationFailed event was useful to delete expired tokens from DB.

@meokullu
Copy link

I added empty alert with someone recommended and it worked. Add Alert {title="tiredOf", message="AppleWorkaround"}

@ZUCheema
Copy link

@AlexBrownShi , try this payload for silent push. It works on iOS 13.
JObject.Parse("{"aps":{"content-available":1}+"}")

I sent silent/background push along with sound and custom data with following payload:
JObject.Parse("{"aps":{"alert":{"title":"" + title + "","body":"" + message + "","badge":"+1","sound":"default"},"content-available":1,"sound":"default"},"data":" + jsonContent + "}")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants