The Certification Authority (CA) for Apple Push Notification service (APNs) is changing. APNs will update the server certificates in sandbox on January 20, 2025, and in production on February 24, 2025. All developers using APNs will need to update their application’s Trust Store to include the new server certificate: SHA-2 Root : USERTrust RSA Certification Authority certificate.
To ensure a smooth transition and avoid push notification delivery failures, please make sure that both old and new server certificates are included in the Trust Store before the cut-off date for each of your application servers that connect to sandbox and production.
At this time, you don’t need to update the APNs SSL provider certificates issued to you by Apple.
Notifications
RSS for tagLearn about the technical aspects of notification delivery on device, including notification types, priorities, and notification center management.
Post
Replies
Boosts
Views
Activity
There is an issue with our app when showing a dynamic watch notification. Our app would sometimes receive a push notification with extra payload. In wOS6, the notification would be sent to the watch and show a dynamic detailed notification based on the data within the notification. But ever since wOS7, the watch does not show the data that is being sent.
We found out that the UNNotification that is being passed through in WKUserNotificationInterfaceController via. [didReceive:notification:](https://developer.apple.com/documentation/watchkit/wkusernotificationinterfacecontroller/2963125-didreceive) has an empty [userInfo](https://developer.apple.com/documentation/usernotifications/unnotificationcontent/1649869-userinfo).
I was wondering if anyone else have that issue. Or was there a change in wOS7 that prevents the userInfo from being received by the watch? Thanks!
I took delivery of my first M1 Mac (iMac running Big Sur 11.4) and with great anticipation installed my iOS VoIP App from the AppStore.
I was greatly disappointed to see that
There were no VoIP Pushes to start an incoming call
Callkit does not seem to work so I get no Audio.
Am I missing something? Is there some permissions or configuration I might need to set?
Or is it just that Callkit and Pushkit don't work even though it states on developer.apple.com that they are supported on macOS 10.15+
Any advice or guidance greatly appreciated.
Very disappointed :-(
I am trying to migrate to the new APNs Provider API.
Here is how I've been registering for push notifications:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//-- Set Notification
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
// iOS 8 Notifications: Registering for notifications and types
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}
else
{
// iOS < 8 Notifications
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];
if (launchOptions != nil)
{
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
NSLog(@"Launched from push notification: %@", dictionary);
/*[self addMessageFromRemoteNotification:dictionary updateUI:NO];*/
}
}
return YES;
}
Within the last week, I have been using the following terminal command from Sending Push Notifications Using Command-Line Tools to successfully send a test push notification to a testing device.
curl -v --header 'apns-topic: com.domain.appname' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Test"}}' --http2 https://api.sandbox.push.apple.com/3/device/258ecf658e25256c8f06ddb1138d5d536ba0e760a96ebd12d3b1dbe112857c58
Recently after creating provisioning profile and adding it to Xcode, the app no longer prints the device token in the debug window.
After removing the provisioning profile from my Apple Developer account under profiles, I tried using a backed up version of the app which still prints a device token to the debugger window.
When I copy the device token and enter it into the terminal command to send another test push notification, the terminal output is a 400 status code : {"reason":"BadDeviceToken"}* Closing connection 1
curl -v --header 'apns-topic: com.domain.appname' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Hello From Faunna"}}' --http2 https://api.sandbox.push.apple.com/3/device/a146d82d4acea02c9ef6de5838174292d0e2cd18a40be17fb79334c5003a0058
* Could not resolve host: alert
* Closing connection 0
curl: (6) Could not resolve host: alert
* Trying 17.188.138.73...
* TCP_NODELAY set
* Connected to api.sandbox.push.apple.com (17.188.138.73) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
Enter PEM pass phrase:
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
* start date: Feb 8 21:41:22 2021 GMT
* expire date: Mar 10 21:41:22 2022 GMT
* subjectAltName: host "api.sandbox.push.apple.com" matched cert's "api.sandbox.push.apple.com"
* issuer: CN=Apple Public Server RSA CA 12 - G1; O=Apple Inc.; ST=California; C=US
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fbd4700aa00)
> POST /3/device/a146d82d4acea02c9ef6de5838174292d0e2cd18a40be17fb79334c5003a0058 HTTP/2
> Host: api.sandbox.push.apple.com
> User-Agent: curl/7.64.1
> Accept: */*
> apns-topic: com.faunna.PushChat
> Content-Length: 37
> Content-Type: application/x-www-form-urlencoded
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!
* We are completely uploaded and fine
< HTTP/2 400
< apns-id: 8DE6AA75-8E41-E95E-1FAF-51D93A8B3200
<
* Connection #1 to host api.sandbox.push.apple.com left intact
{"reason":"BadDeviceToken"}* Closing connection 1
What is causing the bad device token output in this set up? And how should I be registering for remote notifications from this point forward?
Hello everyone!
Our team is in the middle of developing a new sleep tracking app with a bunch of additional features including a custom alarm clock. And we need Critical Alerts entitlement for this feature to work as only such notifications (critical interruption level for iOS 15) can break through Silence Ring & Do Not Disturb mode, which is necessary as users obviously won't wake up without the alarm actually going off.
We've applied twice already, clearly stating the purpose of this entitlement, but both times received the same answer: "Unfortunately, this API is not designed for the use you've identified".
While Apple Developer documentation on the matter is rather elusive and states that, among others, home- & health-related purposes are allowed, I couldn't find any straightforward info about our particular case. Moreover, I can easily name a few apps in the Health & Fitness category with exactly the same alarm clock functionality that works and obviously utilizes Critical Alerts entitlement.
So I wonder, can anyone give a piece of advice on how to get this entitlement? Maybe we need to provide some additional info or meet some unannounced conditions? Any info will be highly appreciated.
What does APS stand for in APS Environment Entitlement?
Hello,
When attempting to assign the UNNotificationResponse to a Published property on the main thread inside UNUserNotificationCenterDelegate's method
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async
both Task { @MainActor in } and await MainActor.run are throwing a NSInternalInconsistencyException: 'Call must be made on main thread'.
I thought both of them were essentially doing the same thing, i.e. call their closure on the main thread. So why is this exception thrown? Is my understanding of the MainActor still incorrect, or is this a bug?
Thank you
Note: Task { await MainActor.run { ... } } and DispatchQueue.main.async don't throw any exception.
It looks like APS Environment is configured by setting the aps-environment value in an app entitlements file to either development or production. However, it seems to be the case that, by default, Xcode automatically overrides the set value when an app is signed and the value is instead derived from the provisioning profile.
So, for development profiles, you get development (sandbox) aps-environment, and for distribution profiles, you get production aps-environment configured - regardless of how the setting has been configured in the entitlements plist.
This is documented here: https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment
That document also states that this default behaviour can be overridden: "These default settings can be modified".
Question is, how to override these default settings. In other words, how to point aps-environment to production, even if provisioning profile is development.
Any insight appreciated, thx.
Hello,
i am implementing Live Activity and facing a problem setting custom color for widget background.
I have a dedicated catalogue of colors for WidgetExtension each having light/dark variant.
The problem is, however, that widget's view changes color variants (any/dark) according to system settings, but not system background & text of widget set via .activityBackgroundTint(_:) and activitySystemActionForegroundColor(_:)
Both widget background and system button texts remain in light variant no matter what system setting was when starting Live Activity.
Later, i was able to kinda force LA background color by checking color scheme in my widget view (yellow and brown for test purposes)
.activityBackgroundTint(colorScheme == .light ? Color.surface. : Color.brown)
this would force Live Activity background to have expected color from start.
BUT
when i later change appearance in system settings Live Activity behaves weirdly, as if it was caching previous color I provided.
I installed 16.2 beta in hope that it was fixed, but noticed this behaviour 👇
system in light mode: LA start, LA background is light
set system to dark: LA background light
set system to light: LA background dark ❗️
set system to dark: do not pull notification center, do not look at LA, instead immediately 👇
set system to light: LA background light
Is there any way around this? 🙏
How to programmatically leave a channel when an app is forced closed? Currently when a user closes the app, the channel remains active and can still talk via the status bar. However i imagine if a user force closes the app, they no longer want to talk.
I tried implementing this via func applicationWillTerminate(_ application: UIApplication) { // leave channel code }
but it doesn't seem to work
Hi,
How can I send push notification for point update and promos to my loyalty wallet users. Currently I get push notification Id when user install loyalty wallet and I use it for sending wallet updates. But when I tried to use this push notification id for custom APN messages it doesn't appear anywhere.
Thank you.
I'm following Apple guidelines to add the Location Push Service Extension to our app.
I followed these steps:
I applied and got approved for Location Push Service Extension.
My app already asks the user for "Always" permissions for location updates
I added the entitlement key com.apple.developer.location.push = TRUE
I added to the project a new Target, and selected Location Push Service Extension from the iOS Application Extension group
I encouter the following issue. When I run the app and call
startMonitoringLocationPushes(completion:)
I receive the following error:
Error Domain=CLLocationPushServiceErrorDomain Code=1 "(null)"
By looking at Apple documentation for CLLocationPushServiceErrorDomain, code 1 stands for:
missingPushExtension
An error code that indicates the app is missing a Location Push Service Extension.
As mentioned beofore I already added the Location Service Extension Target to the project. Any idea of why I receive this error?
Thanks
Hello Everyone!
After push notifications were enabled we got to work on this feature. for our PWA.
The problem that we are having is that they work great for a little bit and then they suddenly stop working. We thought it was our problem but after doing some research I found that many other developers are having this same issue.
Push notifications work perfectly on Android but don't reach ios users.
Is anyone else having the same issue? Can something be done to fix this?
Thanks!!
Hi. I developed a PWA app with fcm because iOS supports push api from iOS 16.4ver
My server push message to fcm with this format.
As you can see, we use webpush.fcmOptions.link to open the url page when users touch notification. On web browser and android, this option works but ios pwa don't. iOS just opens the PWA but can't open the url specified in fcmOptions.link.
Is there anyone who knows about this?
Can I fix it?
We are updating a Live Activity via push notifications quite frequently. As the documentation suggests, we are using NSSupportsLiveActivitiesFrequentUpdates for this case. We are sending all updates with apns-priority: 10.
Is it still possible that iOS throttles push-updates with this setting enabled?
For example we sent updates to APNS in this frequence:
2023-06-09T09:21:22.492224Z
2023-06-09T09:22:03.415876Z
2023-06-09T09:22:05.643268Z
2023-06-09T09:22:08.567353Z
2023-06-09T09:22:11.988442Z
2023-06-09T09:22:17.983494Z
2023-06-09T09:22:28.400757Z
2023-06-09T09:22:44.185622Z
2023-06-09T09:23:06.633058Z
2023-06-09T09:23:23.560052Z
2023-06-09T09:23:31.863625Z
2023-06-09T09:23:37.18351Z
2023-06-09T09:23:44.086319Z
2023-06-09T09:23:49.40655Z
2023-06-09T09:24:08.034848Z
2023-06-09T09:24:18.614194Z
2023-06-09T09:24:20.176428Z
2023-06-09T09:24:25.384654Z
2023-06-09T09:25:03.103147Z
2023-06-09T09:25:15.433726Z
2023-06-09T09:25:21.171693Z
2023-06-09T09:25:23.262028Z
2023-06-09T09:25:28.241116Z
2023-06-09T09:25:30.19816Z
2023-06-09T09:25:32.440543Z
2023-06-09T09:25:42.381815Z
2023-06-09T09:25:50.581656Z
2023-06-09T09:25:55.659846Z
2023-06-09T09:26:15.042667Z
2023-06-09T09:26:26.924626Z
2023-06-09T09:26:28.608762Z
2023-06-09T09:26:32.012874Z
2023-06-09T09:26:39.111211Z
2023-06-09T09:26:40.415326Z
2023-06-09T09:26:51.142985Z
2023-06-09T09:26:54.364073Z
2023-06-09T09:27:04.225692Z
2023-06-09T09:27:30.80347Z
2023-06-09T09:27:33.560981Z
2023-06-09T09:27:42.334313Z
2023-06-09T09:27:43.834646Z
All of those were sent successfully, but at some point the activity stopped updating. The activity continued for several hours after, but was never updated again.
What I checked so far:
From device logs we can see that there was no updated push-token
The sent content-state is correct
From these observations and considering the high-frequent updates, I suspect that there is still some throttling happening here.
Can anyone elaborate on this?
Thanks in advance.
We have an app where the notification service extension works well most of the time. However, sometimes we have noticed that the extension completely stops working even when the notification is sent successfully via the APNS server in production. We do not see even the log from the didReceive() function in that case. The only way we can get the extension working again is after restarting the iPhone.
Trying to understand when this might happen?
Is it something that is throttled by iOS?
Would it happen when the device memory is low or the app is using too much memory?
We have seen the extension crash sometimes due to hitting memory limits, however, the extension process is spawned again when a new notification comes in.
Any kind of help or guidance would be greatly appreciated.
Thanks
We have setup acknowledgment API calls in the notification service extension processing to be notified when the notifications reach the device. So based on that we know how often the devices stop responding with the ACK to sent notifications. It happens seldom with some users and we have to ask them to restart their device to get the extension functional again.
There's an issue in the iOS 17 beta where passing nil to activityBackgroundTint(_:) does not use the system's default background material as expected. Instead, it's showing a solid black color instead of the correct tint that matches the rest of the system in iOS 16.
I am trying to write some code to send a push notification to a pass on an Apple device using C# .NET and HttpClient over HTTP2 with client certificate authentication.
When I run the code, I am seeing the below exception:
InnerException = {"Error 12152 calling WinHttpWriteData, 'The server returned an invalid or unrecognized response'."}
I am trying to find out why this code is failing?
Is it possible to debug/troubleshoot this in some way?
Running this code on Windows 10 OS Build version: 21H2 (19044). The application is built on .Net Framework 4.8 and tried using WinHttpHanlder versions 6 and also 7.
Also, tried using other third party open source libraries like PushSharp and DotApns. PushSharp does not seem to support Http/2 and dotApns does not support certificate authentication for .net framework. We have no plans to migrate to .net Core.
Below is my code:
private static string pushToken = "dbc56849<hidden>";
private static string AppleApnServer = "https://api.sandbox.push.apple.com";
public static async Task<PushResult> SendPushNotificationToWalletPass(string notificationContent)
{
byte[] certificateData = LoadCertificate();
X509Certificate2 certificate = new X509Certificate2(certificateData, String.Empty, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
string url = $"{AppleApnServer}:443/3/device/{pushToken}";
StringBuilder payload = new StringBuilder();
payload.Append("{ \"aps\" : ");
if (string.IsNullOrWhiteSpace(notificationContent))
{
payload.Append("\"\" }");
}
else
{
payload.Append(notificationContent);
payload.Append(" }"); // close aps dictionary
}
var handler = new Http2Handler();
handler.ClientCertificates.Add(certificate);
using (var httpClient = new HttpClient(handler))
{
using (var request = new HttpRequestMessage(HttpMethod.Post, url))
{
var messageGuid = Guid.NewGuid().ToString();
request.Content = new StringContent(payload.ToString());
request.Headers.Add("apns-id", messageGuid);
request.Headers.Add("apns-push-type", "alert");
using (var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
{
HttpStatusCode statusCode = response.StatusCode;
string reasonPhrase = response.ReasonPhrase;
bool success = response.IsSuccessStatusCode;
Console.WriteLine($"APN {(success ? "Delivered Successfully!" : $"Failed to Send! :: StatusCode [{statusCode}] Reason [{reasonPhrase}]")} :: PushToken [{pushToken}]");
if (!success)
{
switch (statusCode)
{
case HttpStatusCode.Gone:
// The device token is no longer active for the topic.
return PushResult.DeviceNotRegistered;
default:
return PushResult.Failure;
}
}
return PushResult.Success;
}
}
}
}
public enum PushResult
{
Success = 0,
Failure = 100,
DeviceNotRegistered = 200
}
// Apple APNS requires http2 but .Net Framework does not support http2 (only built in support in .net core)
// found this workaround https://stackoverflow.com/questions/32685151/how-to-make-the-net-httpclient-use-http-2-0/43101990#43101990
private class Http2Handler : WinHttpHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Version = new Version("2.0");
return base.SendAsync(request, cancellationToken);
}
}
1- Did activate audio session get called in both receiveing and transmiting what the best practice to handle Playback & Recording.
2- how to playback audio after that cuse in background websocket get killed "Software caused connection abort".
Thanks in advance.🙏🏻
iOS 17, the default notification tone is changed to - rebound instead of tri-tone. And now, it is too quite. Also, it can't be changed or replaced. Is it possible that it will be replaced/fixed ????
Hi everyone,
I have two questions regarding some issues with the new iOS 17 interactive widgets and live activities.
Question 1: How can I update other Widgets and/or Live Activities, based on an AppIntent interaction in either one?
I have several widgets that is displaying the same information, but in different sizes (Small, Medium, Large and Lockscreen). Most of our users are using many of them together on their Lockscreen and Home Screen. When they are interacting with the AppIntent button in either the Widget og LiveActivity it does not update and vice-versa.
Based on the documentation it's pretty clear that interacting with a Widget it will update the timeline for that specific widget after the .perform() in the AppIntent is returned. Unfortunately, I also need to update the LiveActivity and the other TimeLines for the rest of the widgets. I have tried to use the WidgetCenter.shared.reloadAllTimelines() but it seems like it does not update the LiveActivity or the LockScreen widgets correctly.
Question 2: How can I update and reschedule the local notifications based on the interaction in the Widget and Live Activity?
The app sends a local notification whenever an activity starts or stops (e.g like a pomodoro timer with intervals). Let's assume the user have setup a 30 minute activity in the app, but now decides to pause the activity from either the widget or live activity. I then want to remove the scheduled local notification that was supposed to be fired in 30 minutes. I haven't been able to read from the documentation if this is possible, but would like to know if there is any way this can be performed.
Looking forward to hear if anyone have encountered the same challenges :)