I'm a little confused on the difference between using Certificate based connections to the APN service verse the Device Token method.
My understanding is, when sending a push notification to an iOS device, my options are either:
A) I could have registered the APN certificate with the Application bundle, and my provider can send it to the APN service to verify I'm allowed to send notifications to devices with that Application bundle.
B) My provider could be sent a "Device Token" via the downloaded application on the device over HTTP, and when I send that Device Token to the APN service, it will know the user has allowed me to send those notifications.
My questions are:
1) If I were to use method A, how could I target certain devices to send the notifications to if I don't have a device token?
2) If I use method B, where would I receive the device token to send silent notifications if my user "Doesn't Allow" push notifications? Will
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
Still run and allow me to pull the deviceToken out, so I can send it via HTTP to my provider?
I've adopted a piece of software that used Certificate based Push Notifications (I think) and was unsure of how it was differentiating who to send notifications to with any deviceTokens. Once I rebuilt and redownloaded the application on my iOS device the notifications stopped working, so I assumed the certificate was no longer associated with the build.
I'm also curious as to how someone can debug notifications on a physical device. I've tried the Console app on Mac and have had little luck seeing any print statements I put in the code.
I'm still very new to iOS programming so please correct me if any of my understanding of the APN Service is wrong! Thank you very much in advance!
There are a few things to understand:
Your Company/Team's Certificate
Your App/Bundle's Provisioning profile
Your Client/User's Device Token
Your BackEnd Server
1 & 2 are bundled in your app when you upload it to App Store.
You get 3 when you ask user the permission for sending PN. [For this 2 should have the capability for remote push notifications enabled]
You give 1 & 3 to 4. [1 for establishing connection with APNS server, 3 to send PN to a specific iOS device]
So, to answer your question: You need both A & B.
For better understanding how APNS works I am attaching a reference diagram that would help to clear your concept for the same.
** If I were to use method A, how could I target certain devices to send the notifications to if I don't have a device token?**
Without Device token, you won't be able to target the iPhones or
idevices on which you want to send the push notification
if my user "Doesn't Allow" push notifications -> then you won't be able to generate PUSH DEVICE TOKEN hence in this scenario you won't be able to receive any push notification.
Related
I'm currently implementing push notifications from our backend server to our app (macOS Catalina & iOS - same code base), using Apple Push Notifications & the token based way of authentication (generating JWT from keyId, teamId, ... & signing it with the private key generated in the Apple developer console) to send pushes to APN service.
The problem I am facing is that I can successfully send "alert" notifications (status 200, with header apns-push-type: alert) and receive them on my iOS and MacOS device (the push notifications appear successfully in production and sandbox mode) but for some reason, "silent" pushes (with header apns-push-type: background) are only received on my iOS device (iPhone), but not on my Mac (didReceiveRemoteNotification(...) in AppDelegate is never called).
What I have done so far:
Made sure APN request header is correctly configured for silent push: apns-push-type: background
Made sure to have the correct APN topic header: apns-topic: my.bundle.id (this is different for sandbox/production)
Added the "semi-required" priority header: apns-priority: 5 (only when delivering background pushes)
Verified that the created JWT is valid and used in the APN auth header: authorization: mytoken (this must be the case, otherwise APN service would not respond with status 200)
Confirmed that my application has the correct entitlements & capabilities defined in Xcode (my reasoning: this must be the case, otherwise 'alert' push notifications would also not work)
Double checked that push notifications for the Mac app are allowed/enabled (checked system settings)
Made sure the device token im sending the push to is actually from the device intended to receive the push (e.g. my MacBook)
Checked that the private key I'm using to sign the JWT has the APN capability
Tested while the Mac app is running but not in focus & also when in focus
The APNs requests I am performing to send the push are:
Sandbox: POST https://api.sandbox.push.apple.com/3/device/{deviceToken}
Production: POST https://api.push.apple.com/3/device/{deviceToken}
The payload (JSON) I'm sending to APN service in the request body looks as follows:
{
"aps": {
"content-available": 1 # defines push as "silent"
},
"data": { #some key-value pairs here }
}
In any case (both production & sandbox, both with the device token of iOS and macOS), my request to APN returns with a status code 200. My MacBook is running Catalina 10.15.3. What am I possibly doing wrong here or is that something that is simply not supported for Catalyst apps?
Wow doozy question. I'm reasonably familiar with APNs headaches but something popped out at me from the latest docs:
Additionally, the notification’s POST request should contain the
apns-push-type header field with a value of background, and the
apns-priority field with a value of 5. The APNs server requires the
apns-push-type field when sending push notifications to Apple Watch,
and recommends it for all platforms. For more information, see Create
and Send a POST Request to APNs.
Does the priority 5 thing make a difference?
Also my usually attempt to fix these problems is to test in an archive as opposed to an Xcode build. AFAIK the prod push server can only send to App Store, ad-hoc, enterprise, or testflight builds, so if you're just building from Xcode I don't think you'd get any push notifications with production apns.
I want to send push notification from a iOS device to another iOS device without using backend server. Is it possible for an iOS device to act like a server and send push notification to APNs server?.
Thanks in advance.
Theoretically you can send Apple Push Notifications from a device directly to another device. All you need are the push certificate of the app, the device token of the device you are sending the notification to, and code that establishes a secure TLS connection to the APNS servers.
However, there are several practical problems that make the use of a server almost mandatory :
You need a single place where all the device tokens of all the devices that installed your app will be sent to and persisted in. The best such place would be a server. Without a server, how would device A send its device token to other devices that want to send it push notifications?
Apple require that you keep connections with the APNS server open for as long as possible and use the same connection for sending many notifications. If you open a connection to APNS server on your device, it will probably be short lived (since devices switch networks frequently, and don't stay connected to the internet all the time). Therefore, if you try to send many notifications frequently, and each time use a new connection to APNS, you will probably be banned (since Apple would treat this as DDoS attack).
If you store the push certificate in each device that installs your app (to allow it to send push notifications to other devices directly), aside from the security issue of storing the certificate in many places, you'll have to publish a new version of your app each time the push certificate expires (once a year), and push notifications would stop working for users who don't upgrade to the new version.
Try NWPusher.
It has an iOS framework for sending pushes and has an iOS demo application that sends push notifications from iOS to iOS.
You also need to consider Server costs (other than maintenance and development time if you code your own server).
By sending the push directly from the app device:
- you obtain a much better scalability (since you don't have to centralize everything on your server)
- you don't have to pay for server cost or other service's cost
You can use for iOS:
- https://github.com/noodlewerk/NWPusher Pusher
And for Android:
- Send push notification GCM by java
After reading and searching, apple MDM client - MDM server interaction seems to be:
When Server wants do sth on devices, it sends a notify to APNS (with device token & AppID for APNS to know which devices and application need to receive notification).
APNS send notify to provided app on provided device
when receive notify from APNS, Apple-MDM-client will connect to server, get command and do the command task on devices.
My questions are:
The application that registered for APNS is my application (MY_APP, not Apple-MDM-client). That means the one which receive notification is my MY_APP. Then how Apple-MDM-client know about the notification in order to connect to MDM server?
The solution can be: MY_APP receive notification, then connect to server, get command and push received commands to Apple-MDM-client, tell Apple-MDM-client do the task. If this approach is correct, how MY_APP can communicate to Apple-MDM-client?
There must be API for that purpose but I can not find it via google...
Please take a look at my answer for your original question:
How does MDM in IOS really work?
MDM is clientless protocol. Your MY_APP is not involved in MDM protocol.
What happens is:
Your server send push notification using device token, topic and PushMagic.
This is a little bit unusual push notification, because you don't specify AppID
(Check "Structure of MDM Messages" section in the MDM documentation
This push message goes directly built-in MDM client
MDM client will go and talk to server (to get new commands)
As you can see your app isn't involved in MDM at all.
I would like to enforce Victors answer(because answers to Apple's MDM are so few on the internet)!
Again, in MDM protocol the is no application that has to subscribe to Apple's push notification service, the iOS is the client here. He will be dealing with handling the requests from APNS, but for this to happen the device must have a special kind of configuration profile installed, named an enrollment profile, which is like a normal configuration profile with two payloads in it: an MDM payload, and a Certificate payload, and thats it! After the user install is, the iOS client is ready to receive requests from APNS.
I want to send push notification without any APNS server and device token,like android there is NO local and push notifications but they can send device to device with out google permissions.
You can NOT send a push notification without using APNs. Why? first you need to understand how the technology works:
You need a certificate for a handshake.
You need a device token to be identified by APNs.
In your app, you have to register to APNs.
The app requests the certificate from APNs (handshake).
The server sends back its certificate.
The app will establish a connection to the server and send the PN certificate to the APN server.
The server will validate that you are a trusted app.
The app requests to create a token.
The server creates a token and sends it back.
In your app you save the token (to do e.g. push notifications to a specific user instead of a broadcast).
End.
So, as you see, you need to establish a trusted connection, the APNs is responsible for creating a token to identify your device within the network, and will be responsible for sending notifications.
For more info you could see:
Apple PNs
I implemented push notification in my app.
It is working fine.
Now the problem is even after i deleted my app from device it is getting the push notifications.
So is there any way to unregister the app from push notification when it is deleted from the device.
Hoping for your help.
Thanks in advance.
In Apple push notification there is something called - Feedback Service. So when a user deletes an app, the service provider should ideally stop sending notifications to that device. But Apple does not notify the service that "this device is not using your app, dont send notifications". So instead you need to poll for this info.
Every day you might need to hit Apple Notification servers asking it to give you device Ids who have deleted your app. Once you get them you mark them in your DB as deleted thereby not sending any more notifications. Hope this is what you wanted.
From Apple Documentation -
... Apple Push Notification Service includes a feedback
service that APNs continually updates with a per-application list of
devices for which there were failed-delivery attempts. The devices are
identified by device tokens encoded in binary format. Providers should
periodically query the feedback service to get the list of device
tokens for their applications, each of which is identified by its
topic. Then, after verifying that the application hasn’t recently been
re-registered on the identified devices, a provider should stop
sending notifications to these devices.
Access to the feedback service takes place through a binary interface
similar to that used for sending push notifications. You access the
production feedback service via feedback.push.apple.com, port 2196;
you access the sandbox feedback service via
feedback.sandbox.push.apple.com, port 2196. As with the binary
interface for push notifications, you must use TLS (or SSL) to
establish a secured communications channel. The SSL certificate
required for these connections is the same one that is provisioned for
sending notifications. To establish a trusted provider identity, you
should present this certificate to APNs at connection time using
peer-to-peer authentication.
Be sure to checkout - Issues with Feedback Service
Having not seen this answer so far, there is a small note in the Apple "Troubleshooting Push Notifications" document.
In short, if you delete the last push enabled app, the persistent connection from the device to Apples push server is broken before the server is told that the app has been deleted.
Solution: keep at least one push enabled app on your device.
There is the explanation from the document:
Issues with Using the Feedback Service
If you remove your app from your device or computer and then send a push notification to it, you would expect to have the device token rejected, and the invalidated device token should appear on the feedback service. However, if this was the last push-enabled app on the device or computer, it will not show up in the feedback service. This is because deleting the last app tears down the persistent connection to the push service before the notice of the deletion can be sent.
You can work around this by leaving at least one push-enabled app on the device or computer in order to keep the persistent connection up. To keep the persistent connection to the production environment up, just install any free push-enabled app from the App Store and you should then be able to delete your app and see it appear in the feedback service.
Recall that each push environment has its own persistent connection. So to keep the persistent connection to the sandbox environment up, install another development push-enabled app."