I've got an iOS app using push notifications via Parse.com, and I'd like to do some testing where notifications are only sent to test devices. If I simply switch over to a development certificate, I presume the notifications won't go to production devices.
However, I'm slightly concerned about doing something wrong and accidentally trying to send hundreds of thousands of push notifications to production devices via the development certificate.
I know the production devices would not receive the notifications, but would there be any wider issue to something like this happening - i.e. my app getting flagged as spam or something like that?
If you try to send notifications to production device tokens using development certificate (and connecting to APNS sandbox server), you'll get an error of invalid device token for each notification and the connection will be closed after each message you send. Most of the messages won't even reach Apple, since they close the connection once they find an invalid message, and all the messages sent after that message are discarded.
A bigger problem would be if you store sandbox (=development) device tokens in the same DB as the production tokens. If you don't distinguish between the two types of tokens, when you switch back to production push notifications, you run the risk of trying to send notifications to sandbox tokens using the production push certificate, which would give you errors and close your connection to APNS, thus disrupting the push to the production tokens. Therefore I strongly suggest that you use a different DB to store the sandbox device tokens.
Related
I currently have an application that sends push notifications to APNS, if I run this application locally on my computer (where i do my development) it sends the push notification without any error, however once i put the application on my linux server the exact same code with same device tokens fails to send and receives a "BadDeviceToken" error from APNS.
What would cause me to get this error on my server but not on my local computer? The .p12 certificate I have on my server is taken from my development APNS cert in my keychain on my local computer.
Any suggestions would be very helpful!
So I didn't realise that using Test flight actually requires production apps certificates.
Changed to using them and it all worked, apple should really have a different error message for that case so people don't spend all that time debugging the device token...
We have a (mostly) successful implementation of push notifications to iOS and Android devices through Azure Notification Hubs.
The problem is that some of the iOS devices are apparently never receiving notifications that are sent by Azure Notification Hubs.
We use templates and tags to direct the messages to the appropriate devices. The tags are interest topics, and never user-specific, so we're expecting one notification for a tag to be pushed to all devices subscribed to that tag.
The Android devices seem to receive their notifications flawlessly, but the iOS devices are not consistent. Most of them work. A couple do not.
We are well aware that push notifications are delivered with best effort and have no guarantee of reliability, but our limited testing has revealed more devices which consistently fail to receive push notifications than seems unreasonable (more than two failures from about a dozen devices).
Here's the setup:
We have a simple C# routine in the back end which connects to Azure Notification Hubs and sends notifications to Azure:
var outcome = await hub.SendTemplateNotificationAsync(properties, tag);
We have used the GetAllRegistrationsAsync method to make sure that every device we are checking has successfully registered and is using the correct template. Every device is registered, all the templates are correct.
We are not in "test mode"; the enableTestSend parameter of NotificationHubClient.CreateClientFromConnectionString is set to False.
Troubleshooting:
When we send the notification out, most devices receive the notification and, in the specific case we're testing, update the badge counter with the correct number.
However, a couple of devices do not seem to get the notification. One of the devices did get the notification after we rebooted the device, but after that it stopped.
Using the above mentioned GetAllRegistrationsAsync method, we have verified that the problem devices are correctly registered on Azure and have the correct tags and templates.
We were able to determine the device tokens of the problem devices from the Azure registrations. We used a PHP script which communicates directly with APNS to send a notification just to the problem devices using their device tokens. Every time, the device receives this direct-send notification. It's only the notifications from Azure which are unreliable.
When we examine the Azure Notification Hub Monitor page, we see these metrics for the past 24 hours:
967 APNS Successful Notifications
3 APNS Bad Channel Errors
2 APNS Expired Channel Errors
4 APNS Errors
... and no other errors reported for APNS or for Azure in general. The failure rate we're seeing should have produced an error count over 20.
We have not been able to determine which device tokens were responsible for the errors; is there a way to get this information from Azure?
We're at a loss to explain why we can send notifications directly to these devices over APNS itself, but not through Azure, and why it is that Azure doesn't report more errors than it does.
Any suggestions or insights?
It's quite possible that you have some sandbox device tokens in your database (I'm not sure if the device tokens are stored in your server or in Azure Notification Hub). When trying to send a notification with a sandbox device token to the production push environment, an InvalidToken error is returned by Apple, and the connection is closed.
Very often, by the time the server that sends push notifications to Apple's APN server gets the error response, it has already sent many more notifications (possibly with valid tokens), and all of which are discarded by Apple. At this point, new notifications are accepted by Apple only after a new connection with APNS is established, so messages that were sent after the invalid token to the old connection need to be resent. It is possible Azure don't handle this resending correctly.
As you said, the Azure Notification Hub Monitor page shows a few errors. I suspect that 3 APNS Bad Channel Errors means invalid device tokens. I don't know how many invalid device tokens you actually have in the DB, but even one can cause many notifications with valid tokens not to be accepted by Apple.
The best solution is to test all the device tokens in the DB and figure out the ones that are invalid and delete them.
I developed a web API for my mobile app use it.
This API was developed with Django, and I'm using the django-push-notifications lib to handle the push notifications.
The push notifications were working fine for all the devices, until it stopped working for few of them, which worked at some point, for no apparent reason.
I already debugged the server and I can see the messages being sent to APNS and on the correct format. Also reviewed the certificates, and all is working as it should. I'm using the production certificate sending to the appropriate server.
I'm sure that this is not a problem with certs, since some other phones receive the notifications.
Where should I start looking for the problem now?
Thanks.
They are not reliable! There is no guarantee that push notifications will actually be delivered, even if the APNS server accepted them.
As far as your server is concerned, push notifications are fire-and-forget; there is no way to find out what the status of a notification is after you’ve sent it to APNS. The delivery time may also vary, from seconds up to half an hour.
Also, the user’s iPhone may not be able to receive push notifications all the time. They could be on a WiFi network that does not allow connections to be made to APNS because the required ports are blocked. Or the phone could be turned off.
See this link
Are you sure that those some devices does't have a development version of app ?
Try to generate a combined p12 certificate of apn development certificate and apn production certificate , than try to call gateway.push.apple.com and gateway.sandbox.push.apple.com separately.
My app is already on the app store and with push notifications active and working (using production certificate). Now I need to add badges (before their were only alerts) in the application (already implemented on the server side). So for testing I would need a development SSL certificate. So following are my queries:
Do I have to install the development SSL certificate on my server so that I can test on iPhone using development cert?
Will it not conflict with the already installed production SSL cert on the server.
Do I have to add badges in both didReceiveRemoteNotification: and didFinishLaunchingWithOptions: delegates using below code:
code section:
NSString* alertValue = [[userInfo valueForKey:#"aps"] valueForKey:#"badge"];
NSLog(#"my message-- %#",alertValue);
int badgeValue= [alertValue intValue];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeValue];
Any suggestions?
Just to add some additional color to the Certificate/Server/SSL questions and answers that have been proposed:
Prod/Sandbox APNS Picked Based on Codesign Settings
For the sake of being thorough, lets start with a quick review of the APNS environment:
Applications that are Code Signed with an iOS Development certificate connect to and wait for Push Notifications to be delivered from the Sandbox APNS Environment
Applications that are Code Signed with an iOS Distribution certificate (AppStore or Distribution > Ad-Hoc) connect to and wait for Push Notification to be delivered from the Production APNS Environment.
This setting is automatically determined by Xcode during the build process and is only configurable by selecting the type of certificate used in the CodeSign step.
Question 1: Do I have to install the Development SSL Certificate on my Server to Test Development Certificate Signed Apps Push Notifications?
Yes, once and app is Code Signed, its APNS setting is sealed into the binary using the rules in the previous section. It is then up to the Developer's server code to know that the APNS token that device will generate goes with the Sandbox APNS environment and that the server should route that request for a push notification to gateway.sandbox.push.apple.com instead.
Some developers choose to setup a single server that is capable of making these distinctions while others choose to setup side-by-side instances of their servers one set to send to Production and another set to send to the Sandbox.
Either way, the decision resides with the individual developer and what their server-side code is capable of doing and the relative complexity of setting up a second server. Either way, users might get upset if you accidentally disabled Production push notifications while testing out upcoming features then forgot to reenable them later, so definitely be careful when poking around production code!
Question #2: Will the Development and Production SSL Certificate Conflict?
From the raw SSL standpoint no they won't conflict -- you should be able to download and open/examine both of those certificates on a machine other than the server and see that the contents of the certificates are in fact different. Importing them into the same server environment (again from an SSL perspective) is perfectly allowable. To ensure they are different, when requesting the certificates make absolutely sure you create two different certificateSigningRequests and you'll inherently wind up with different data.
From the Developer's Server-side Push Code standpoint -- It depends. See the conversation in Question 1 regarding server-side code capabilities. If the server-code was designed with this in mind then in theory the answer is also 'No they will not conflict', but that is a determination the individual developer needs to make about their own server-side code capabilities.
Yes, you should install the development SSL certificate on server. You also have to use sandbox push-notification service (gateway.sandbox.push.apple.com) with this certificate.
I guess they won't conflict. You should just use production SSL for AppStore app, and development SSL for test app.
It's better not to increment or decrement or set badge value in code. Your server should return badge value in notifications body. For example, You can't handle push when your app is not running, thus you cant change badge value in code. But if your push contains badge value, it will be set and displayed correctly any way.
Here is the notification body example. Pass badge value for key "badge":
{"aps":{"alert":"This is message.","badge":7}}
By the way, didReceiveRemoteNotification: method always called when you app receives push. Even if the app is down, it will be called when you launch the app from push.
I just wanted to add something to the existing answers. While the development cert won't conflict with the production cert installed on the same server, you might get conflicts with the device tokens stored in your DB. When you use a development cert, you get development device tokens from Apple, which are not the same as the production device tokens you'll get for your production cert. If you keep both development and production device tokens in the same database (which you probably will if you use the same server for both development and production), you will have trouble if you send notifications with development device token using the production cert or vica versa.
That's why it is recommended by Apple to use separate servers for development and production.
This quote is taken from Troubleshooting Push Notifications, which is a very useful document :
The most common problem is an invalid device token. If the token came
from the sandbox environment, such as when you are testing a
development build in house, you can't send it to the production push
service. Each push environment will issue a different token for the
same device or computer. If you do send a device token to the wrong
environment, the push service will see that as an invalid token and
discard the notification.
Note: It is recommended that you run a separate instance of your
provider for each push environment to avoid the problem of sending
device tokens to the wrong environment.
We are trying to send a notification to ~500,000 iOS devices. We have currently set the batch size to 200 and are noticing that Apple refuses our connection after 300k messages or so. We suspect that Apple interprets our connection/tear-downs to be a DOS attack. What is a good batch size for us to use? Also, any tips on sending notifications for such a large number of devices?
Your push notification server must maintain a persistent connection to Apple's socket stream push server without disconnecting too often.
I recommend writing your push server using Node.js, it was designed for this stuff.
However there are a few things that can also cause Apple to disconnect your push server.
With Push Notification, there are two types of certificates - development and production.
An app signed with a development certificate will generate a development push token whereas a an app signed with a production certificate will generate a different production push token even on the same device.
Your server must make sure it does not send a development token to a production socket stream connection to Apple's push server.
Mixing the token and environment will cause Apple's push server to disconnect your push server.
How you separate your push token is something that you need to build into your server.
Hope that helps.