Our Java backend application is responsible for sending millions of push notifications. However, we are encountering an issue where thousands of connection resets occur daily. This irony leads to an inability to keep up with the volume, resulting in a lag that affects real-time performance.
The application is built on Java, utilizing JDK 1.8 and the Apache HttpClient for network communications. Below is the Maven dependency we use:
XML
Additionally, we employ Spring’s RestTemplate to dispatch push notifications. Here is a snippet of the pseudo-code used to call the Apple Push Notification service (APNs):
Java
ResponseEntity postForEntity = restTemplate.postForEntity(apnsURL, entity, responseType);
getResponse(aPNSResponse, postForEntity);
AI-generated code. Review and use carefully. More info on FAQ.
It’s important to note that our calls to APNs are not made directly but are routed through an F5 load balancer, which then communicates with the APNs endpoint.
Could someone guide us in the right direction to resolve these connection reset issues?
APNS
RSS for tagSend push notifications to Mac, iOS, iPadOS, tvOS devices through your app using the Apple Push Notifications service (APNs).
Posts under APNS tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
When a request comes from the server, I want to set the screen time API of the requested phone or retrieve usage information. I would like to use silent push to complete that action in the background.
Is it impossible for the Screen Time API to run in the background?
When a user receives a provisional notification and they click the "Keep" button and choose deliver immediately, there is no OS setting changes. The notifications are stuck in "delivered quietly" unless the user happens to change that in their Settings.
The ActivityKit API requires developers to parameterize calls to pushToStartTokenUpdates by the live activity's attributes, e.g.
for await data in
Activity<AdventureAttributes>.pushToStartTokenUpdates {
// Send token to server.
}
for await data in
Activity<BoringAttributes>.pushToStartTokenUpdates {
// Send token to server.
}
At runtime, I have noticed that the token is the same for the different live activity attribute types we support in our app.
Can someone confirm if this behavior is consistent? If the pushToStartToken is the same across different live activity types, it can simplify our database design 🙏🏼.
Nous souhaitons activer l'entitlement com.apple.developer.usernotifications.filtering pour notre extension MsgNotificationService. Pourriez-vous nous fournir des instructions supplémentaires ou activer cet entitlement pour notre App ID ? Si des informations supplémentaires sont nécessaires ou des étapes spécifiques doivent être suivies.
actuellement cela n'a pas d'impact sur le build mais sur le product->archive. impossible upload le build
Une idée, un conseil ?
Merci,
App getting terminated as the app enters background state. No crash logs are generated.
I have collected this log from Console(Mac app)by connecting iPhone and sending my app to background.
There is no meaningful reason or code I can get from the logs. Can you please help me with what does 'explanation:BG Kill Demo ' means ?
My app is a VoIP app. App depends on voip apns notifications to receive information about new Voip calls from server.
I am posting the logs collected from console app here.
default 14:29:55.265590-0400 audiomxd -CMSessionMgr- CMSessionMgrHandleApplicationStateChange: Sending stop command to com.myapp.bundleid with pid '2933' because client is background suspended and there is no AirPlay video session for it
default 14:29:55.265753-0400 dasd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.265908-0400 locationd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.265994-0400 locationd {"msg":"invoking applicationStateChange handler", "StateChangeData":"{\n BKSApplicationStateAppIsFrontmost = 0;\n BKSApplicationStateExtensionKey = 0;\n SBApplicationStateDisplayIDKey = "com.myapp.bundleid";\n SBApplicationStateKey = 2;\n SBApplicationStateProcessIDKey = 2933;\n SBMostElevatedStateForProcessID = 2;\n}"}
default 14:29:55.266083-0400 locationd {"msg":"Post Application State Change Notification", "notification":"BackgroundTaskSuspended", "pid":2933, "bundleId":"com.myapp.bundleid"}
default 14:29:55.267019-0400 locationd {"msg":"#CLIUA AppMonitor notification", "notification":"BackgroundTaskSuspended", "pid":2933, "bundleId":"com.myapp.bundleid", "ClientKey":"icom.myapp.bundleid:"}
default 14:29:55.267061-0400 locationd {"msg":"skip erasing #CLIUA for RunningBoard Process State. Does not exists", "bundleId":"com.myapp.bundleid"}
default 14:29:55.267678-0400 watchdogd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.267765-0400 useractivityd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.267934-0400 symptomsd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.267982-0400 wifid Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.268228-0400 UserEventAgent Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.268275-0400 callservicesd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.268338-0400 WirelessRadioManagerd Received state update for 2933 (app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>, running-suspended-NotVisible
default 14:29:55.269217-0400 runningboardd Acquiring assertion targeting [app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933] from originator [osservice<com.apple.dasd>:76] with description <RBSAssertionDescriptor| "DAS: Application is docked." ID:33-76-44901 target:2933 attributes:[
<RBSDomainAttribute| domain:"com.apple.dasd" name:"DockApp" sourceEnvironment:"(null)">
]>
default 14:29:55.269572-0400 runningboardd Assertion 33-76-44901 (target:[app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933]) will be created as active
default 14:29:55.270431-0400 runningboardd [app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933] Set jetsam priority to 30 [0] flag[1]
default 14:29:55.270658-0400 runningboardd Calculated state for app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>: running-suspended (role: None) (endowments: (null))
default 14:29:55.273005-0400 runningboardd Received termination request from [osservice<com.apple.dasd>:76] on <RBSProcessPredicate <RBSProcessHandlePredicateImpl| app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933>> with context <RBSTerminateContext| explanation:BG Kill Demo reportType:None maxTerminationResistance:Interactive>
default 14:29:55.274715-0400 runningboardd Executing termination request for: <RBSProcessPredicate <RBSProcessHandlePredicateImpl| app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933>>
default 14:29:55.275034-0400 runningboardd [app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933] Terminating with context: <RBSTerminateContext| explanation:BG Kill Demo reportType:None maxTerminationResistance:Interactive>
default 14:29:55.275122-0400 runningboardd [app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933] terminate_with_reason() success
default 14:29:55.275768-0400 SpringBoard [app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933] Workspace connection invalidated.
default 14:29:55.275790-0400 SpringBoard [app<com.myapp.bundleid(AD9F24FF-321B-48U6-895F-723CDA943372)>:2933] Now flagged as pending exit for reason: workspace client connection invalidated
default 14:29:55.275815-0400 backboardd Connection removed: IOHIDEventSystemConnection uuid:C2525EA6-A052-480B-B83D-4BD62C29C6EC pid:2933 process:MyApp type:Passive entitlements:0x0 caller:BackBoardServices: + 280 attributes:{
HighFrequency = 1;
bundleID = "com.myapp.bundleid";
pid = 2933;
} state:0x1 events:9 mask:0x800 dropped:0 dropStatus:0 droppedMask:0x0 lastDroppedTime:NONE
default 14:29:55.275988-0400 backboardd Removing client connection <BKHIDClientConnection: 0xd43cd1f40; IOHIDEventSystemConnectionRef: 0xd415d5800; vpid: 2933(v1C3E); taskPort: 0x84D8B; bundleID: com.myapp.bundleid> for client: IOHIDEventSystemConnection uuid:C2525EA6-A052-480B-B83D-4BD62C29C6EC pid:2933 process:MyApp type:Passive entitlements:0x0 caller:BackBoardServices: + 280 attributes:{
HighFrequency = 1;
bundleID = "com.myapp.bundleid";
pid = 2933;
} state:0x1 events:9 mask:0x800 dropped:0 dropStatus:0 droppedMask:0x0 lastDroppedTime:NONE source:HID
default 14:29:55.288098-0400 runningboardd [app<com.myapp.bundleid(AD9F24F321B-48U6C7-895F-723CDA943372)>:2933] termination reported by launchd (15, 0, 9)
default 14:29:55.289192-0400 runningboardd Removing process: [app<com.myapp.bundleid(AD9F24F321B-48U6C7-895F-723CDA943372)>:2933]
default 14:29:55.289331-0400 runningboardd Removing launch job for: [app<com.myapp.bundleid(AD9F24F321B-48U6C7-895F-723CDA943372)>:2933]
default 14:29:55.289582-0400 runningboardd Removed job for [app<com.myapp.bundleid(AD9F24F321B-48U6C7-895F-723CDA943372)>:2933]
default 14:29:55.289706-0400 runningboardd Removing assertions for terminated process: [app<com.myapp.bundleid(AD9F24F321B-48U6C7-895F-723CDA943372)>:2933]
I've implemented pass generation successfully and it's updated through Apple's silent notification, which updates the passes to their latest versions.
I want to send some marketing push notifications to the Apple Wallet App as shown in my post at stackoverflow.
Here is the Silent notification implementation, which is working perfectly fine.
const options: apn.ProviderOptions = {
token: {
key: fs.readFileSync("./certs/APNs_AuthKey_7YYF346FU5.p8"),
keyId: "******",
teamId: "******",
},
pfx: fs.readFileSync("./certs/private_key.pem"),
cert: fs.readFileSync("./certs/certificate.pem"),
production: true,
rejectUnauthorized: true,
};
const apnProvider = new apn.Provider(options);
async function sendSilentPushNotification(
deviceTokens: string[],
serialNumber: string
) {
try {
const notification = new apn.Notification();
notification.topic = "pass.com.digital.passmaker";
notification.payload = {
aps: {
"content-available": 1,
},
serialNumber,
};
notification.priority = 5;
return await apnProvider.send(notification, deviceTokens);
} catch (error) {
logger.error("Apple Notification error: " + error);
return error;
}
}
Here is the marketing notification I am trying to send, it is working with success, but I don't see any notification on mobile phone.
please help me to fix it.
async function sendCustomPushNotification(
deviceTokens: string[],
serialNumber: string,
title: string,
body: string,
category?: string,
badge?: number
) {
try {
const notification = new apn.Notification();
notification.topic = "pass.com.digital.passmaker";
// Set the title and body of the notification
notification.alert = {
title: title,
subtitle: "Pass Update",
body: body,
};
// Set the sound to play when the notification is received
notification.sound = "default";
// Set the badge number on the app icon (optional)
if (badge !== undefined) {
notification.badge = badge;
}
notification.contentAvailable = true;
notification.mutableContent = true;
notification.aps.category = category;
notification.aps.alert = {
title: title,
body: body,
};
notification.aps.badge = badge;
notification.aps["content-available"] = 1;
notification.aps["launch-image"] =
"https://banner2.cleanpng.com/20180423/gkw/.......jpg";
// You can still include the serialNumber in the custom payload
notification.payload = {
serialNumber: serialNumber,
aps: {
"content-available": 1,
"mutable-content": 1,
"interruption-level": "time-sensitive",
},
};
// Set to high priority
notification.priority = 10;
return await apnProvider.send(notification, deviceTokens);
} catch (error) {
logger.error("Apple Notification error: " + error);
return error;
}
}
I literally receive a success response from api returning the device pushToken with no errors. However, no notification show on my iPhone
Hi,
we noticed some issues with our app when it comes to receiving pushs sent when a device was offline. We know that only one push is stored if multiple are received while the device was offline but we got reports of multiple users that aren't receiving any pushs that were sent while they were offline. Reinstalling the App didn't help.
We ruled out the third-party providers we used as my first thought was that there was some issues with setting the expiry but it also happens if directly sent over APNs.
With a development build and the sandbox APNs I had no issue receiving one push after getting back online. But after reinstalling the production app no push after being offline.
Example sent with the Push Notifications Console but I also tested it with curl directly:
curl -v \
--header "authorization: bearer ${AUTHENTICATION_TOKEN}" \
--header "apns-topic: de.alarm-it-factory.ACC-App-Xamarin" \
--header "apns-push-type: alert" \
--header "apns-priority: 10" \
--header "apns-expiration: 1721379960" \
--data '{"aps":{"alert":{"title":"Test","body":"Expiry Test 4"}}}' \
--http2 https://api.push.apple.com:443/3/device/46F201D299F2B900CF3BF3096341116B9D5A69D103F2C0ACF18634823F73AB79
Sent: 15. Juli 2024, 16:00:42,361 MESZ
Received: not received
Topic: de.alarm-it-factory.ACC-App-Xamarin
BundleID: de.alarm-it-factory.ACC-App-Xamarin
Token: 46F201D299F2B900CF3BF3096341116B9D5A69D103F2C0ACF18634823F73AB79
apns-id: ec14fba2-efa5-4ace-9e22-3e4e5a64d630
I sent test messages before and after acivating airplane mode to make sure I have the correct token.
Hi all,
I'm attempting to implement a notification service extension for my app, however I'm running into some troubles with triggering the extension.
The service extension is successfully installed with the app, and is initialized when a notification is received (which ive confirmed by attaching a debugger to it), however the didReceive method is never called. In the debugger console, the following message is printed: Service extension base class recieved didReceiveNotificationRequest: .
I can confirm that the all the payload requirements are met to trigger the extension, and I was able to create an extension that would trigger in a blank application (using the same payload). It's only this app that prints this message to the console, and does not trigger.
The extension code is as follows (I've removed all of the intended functionality at this point to try and pinpoint the issue)
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override init() {
self.contentHandler = nil
self.bestAttemptContent = nil
print("startup!")
}
func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) async {
let logger = Logger(subsystem: "app.revolt.chat", category: "notificationservice")
logger.info("Invoked notification extension")
debugPrint(request)
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
guard let bestAttemptContent = bestAttemptContent else {
print("content is null")
return
}
bestAttemptContent.title = "beans"
if request.content.categoryIdentifier != "ALERT_MESSAGE" {
bestAttemptContent.subtitle = "not an alert message"
contentHandler(bestAttemptContent)
return
}
contentHandler(bestAttemptContent)
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Hi,
We've implemented the new Live Activity Broadcast push notifications (https://developer.apple.com/documentation/usernotifications/setting-up-broadcast-push-notifications) and are testing this out in sandbox/development.
Looking at our logs I can see that we tried to send 54 broadcast notifications the last hour. 16 of these failed with "429 Too Many Requests".
We probably have no devices registered on any of the channels at the moment. These are all channels from the "Development" environment.
Any pointers to what could be wrong?
Regards,
-Tommy
hi, I am trying to schedule a UNNotificationRequest at a certain date using UNCalendarNotificationTrigger, and I also want to update the badge count accordingly. However the badge property in UNNotificationContent can only be set when adding UNNotificationRequest, not when the trigger is fired or notification is actually delivered. How can I set up-to-date badge count if notification is scheduled in the future?
For example, if I scheduled notification A to 3 hours later with badge count 1, and in between I got notification B, badge count should be 2 when A is delivered but it will be 1.
I am aware of didPresent delegate which can be used when app is in foreground when notification is delivered, but is there any delegate that is called when UNNotificationRequest is delivered and app is backgrounded or we are using NSE? Thanks.
Hello,
I have developed an update for my app where I handle push notifications (from APNs or FCM) and manage different notification categories using checks, storing the values in UserDefaults. So far, everything works fine, and the logs correctly indicate the state of each category when a notification is received.
The issue arises when handling notifications in three states: foreground, background, and terminated (killed). I am using UNNotificationServiceExtension and in the didReceive method, I check the state of the notification. Depending on whether the state is true or false, I want the notification to be shown or not to the user. However, despite my efforts, the alert/notification part of the payload always ends up being displayed.
Additionally, I have disabled serviceExtensionTimeWillExpire as it was being triggered, but still, after a few seconds, the notification ends up appearing.
I have configured everything correctly, including mutable content, notification handling, etc. How can I prevent these notifications from being shown to the user when needed?
Thank you for your assistance!
按开发者文档进行请求,响应405
接口文档:https://developer.apple.com/documentation/devicemanagement/activation_lock_a_device
实际请求如下:
curl --location --request POST 'https://mdmenrollment.apple.com/device/activationlock'
--header 'X-ADM-Auth-Session: 1720513551341O1O293...'
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)'
--header 'Content-Type: application/json'
--header 'Accept: /'
--header 'Host: mdmenrollment.apple.com'
--header 'Connection: keep-alive'
--data-raw '{"device": "FNXQX..."}'
这个问题要怎么解决?
We are experiencing issues with Push Notification delivery for our Lulu Money application (com.lulu.luluone) using Apple ID 1163514668.
Upon reviewing the Push Notifications console, we have found that out of the 7.294M Priority Notifications sent in the last 4 weeks, only 1.226M were delivered to the device. The majority of the undelivered notifications, totalling 5.479M, are categorized as "Stored - Device Offline."
This issue is negatively impacting our customers, and we need assistance in resolving it to ensure smooth notification delivery.
I am working on a VoIP based PTT app. Uses 'voip' apns notification type to get to know about new incoming PTT call.
When the app is in foreground, the app gets to know about incoming VoIP PTT call through incoming push notification. After receiving notification, the app receives audio from the server. This works properly, as expected.
The app faces issues in receiving apns notifications only when the app is in background.
Issue: My app is in background and iPhone locked, the server sends apns notification to the target iPhone about a new incoming VoIP call. Server received 200 success response code from APNS. But the app in background did not receive the notification. Second time, the server sends notification about second VoIP call. App did not receive notification. Third time, server sends notification about 3rd incoming call. This list goes on. Everytime server sends a notification to the target phone, success response is received from APNS.
Now, bring the app to foreground, the app receives all the pending notifications at once. This scenario happens only in a few phones. Those customers are missing PTT calls.
Can you please provide us suggestions to solve this issue ?
My app uses unrestricted-voip entitlement
I am working on a VoIP based PTT app. Uses 'voip' apns notification type to get to know about new incoming PTT call.
When my app receives a PTT call, the app plays audio. But the call audio is not heard. While checking the phone volume, the API [[AVAudioSession sharedInstance] outputVolume] returns 0. But clearly the phone volume is not zero. On checking the phone volume by pressing side volume button, the volume is above 50%.
This behavior is observed in both app foreground and background scenario.
Why does the API return zero volume level ? Is there any other reason why the app volume is not heard ?
I have been trying to solve this issue for the last four day. Can any one help.
Than you.
I was able to successfully archive my main app that has a NotificationServiceExtension.
However, once I installed the app via Testflight, I was able to receive a notification, but the push notification modifications I did were not applied.
When I just ran it via Xcode, the push notification modifications worked.
Do I need to archive the NotificationServiceExtension instead of my main app?
I am unable to receive push notifications through my Apple Wallet pass. Based on the documents I have read, I have set up my APN provider and should be sending all the necessary information. Furthermore, my logs show that I am successfully sending my notification to APN, so it is confusing that no notification appears on my phone. Below are my code snippets:
apnProvider.js:
const path = require('path');
const options = {
cert: path.resolve(__dirname, '../certificates/signerCert.pem'),
key: path.resolve(__dirname, '../certificates/signerKey.pem'),
passphrase: 'test',
production: true
};
const apnProvider = new apn.Provider(options);
module.exports = apnProvider;
APN provider using an auth key (currently not being used but was previously and provided the same success message):
token: {
key: path.resolve(__dirname, '../certificates/AuthKey_627HR2YX2S.p8'),
keyId: "627HR2YX2S",
teamId: "72J45J9PH3"
},
production: true
});
API Rout:
const { userId } = req.body;
console.log(`Received POST request on /api/send-notification for user`);
try {
console.log(`Sending notification to user: ${userId}`);
const user = await User.findById(userId);
if (user && user.deviceToken) {
console.log('User Name:', user.firstName, user.lastName);
console.log('Device Token:', user.deviceToken);
let notification = new apn.Notification();
notification.expiry = Math.floor(Date.now() / 1000) + 3600;
notification.badge = 1;
notification.sound = 'default';
notification.alert = 'Hello World';
notification.payload = { messageFrom: 'Kudjo' };
notification.topic = 'pass.com.kudjo';
console.log(`Sending notification to device token: ${user.deviceToken}`);
console.log(`Notification payload:`, notification.payload);
apnProvider.send(notification, user.deviceToken).then(response => {
console.log('Push notification sent:', response);
res.status(200).json({ message: 'Notification sent' });
}).catch(error => {
console.error('Error sending push notification:', error);
res.status(500).json({ message: 'Error sending notification One' });
});
} else {
console.log('User or device token not found');
res.status(404).json({ message: 'User or device token not found' });
}
} catch (error) {
console.log('Error sending notification:', error);
res.status(500).json({ message: 'Error sending notification Two' });
}
});
Thank you for your help!
Hello, I would like to implement the function of unsubscribe FCM topics that I was subscribing to when I received a specific push from the server.
It was implemented through "willPresent" when the app was running, but I don't know how to do it when the app is not running.
I activated the 'Background fetch' and 'Remote Notifications' options for now.
const message = {
notification: {
title: 'FCM Topic UnSubscribe',
body: 'TestTestTest',
},
data: {
payload: JSON.stringify(payloadJson)
},
apns: {
payload: {
aps: {
sound: 'default',
'mutable-content': 1,
'content-available': 1
}
}
},
topic: 'unsubscribe_topic',
};
Test node code
Payload contains the type of topic you want to unsubscribe from.
And I added a function to receive push from didReceiveRemoteNotification and handle logic.
But this doesn't work.
Does Remote Notification (content-available) not work in iOS's Not running and Suspended state??
I'm also using the Notification Service Extension, is this related to it?