I am using the Huawei Push Toolkit to send push messages to customers. There is a mechanism where the push tokens of each device are often refreshed, so a token used right now might be different than a token used, say, a day ago.
The issue was that if we try to send a push to a token that was valid only yesterday, the response is:
{ "code": "80000000"
"msg": "Success",
"requestId": "161615569495608835000107"
}
However, naturally, the device didn't receive the push because it was in the meantime refreshed. If sending it to the most up-to-date push token, the response is still the same and the device does get the message.
Why didn't the API return a different response, say, the error code `80300007` (all tokens invalid) in the first scenario? This is consistently replicated even for tokens older than 1 day (tested as far back as a 25 days old token).
reference
The endpoints tested were: https://push-api.cloud.huawei.com/v2/.../messages:send
and https://push-api.cloud.huawei.com/v1/.../messages:send
Both have the same behavior.
The situation you experience with the device token is normal for the Push server and it is about the information flow and the return value is just a presentation of the current node. To explain briefly 1. The Access Token is used only for the authentication interface. If the AT does not expire after the authentication succeeds, no error is reported. 2. The server pushes messages through the Push interface. If success:80000000 is returned, the Huawei Push server has received the messages, but this does not mean that the messages can be pushed to the terminal.
Related
I am using push notifications in meteor app for ios and android. It works fine if the users to whom I am sending the notifications are connected to the internet. The problem that if I send a notification to an offline user and when he connects to the internet after few hours, the notification is not delivered. Any insights as how to overcome this.
Following is my code to send notifications :
Push.send({
from: '1234',
title: title,
text: text,
notId : nId,
gcm: {
title: title,
style: 'inbox',
},
query: {
userId: {
$in: userIds
},
}
});
I couldn't find TTL(Time To Live) option in the gitRepo you provided.. usually there is an option for that.. You can read more about that here concept options
Update
New Link
Lifetime of a message When an app server posts a message to FCM and
receives a message ID back, it does not mean that the message was
already delivered to the device. Rather, it means that it was accepted
for delivery. What happens to the message after it is accepted depends
on many factors.
In the best-case scenario, if the device is connected to FCM, the
screen is on and there are no throttling restrictions, the message is
delivered right away.
If the device is connected but in Doze, a low priority message is
stored by FCM until the device is out of Doze. And that's where the
collapse_key flag plays a role: if there is already a message with the
same collapse key (and registration token) stored and waiting for
delivery, the old message is discarded and the new message takes its
place (that is, the old message is collapsed by the new one). However,
if the collapse key is not set, both the new and old messages are
stored for future delivery.
If the device is not connected to FCM, the message is stored until a
connection is established (again respecting the collapse key rules).
When a connection is established, FCM delivers all pending messages to
the device. If the device never gets connected again (for instance, if
it was factory reset), the message eventually times out and is
discarded from FCM storage. The default timeout is four weeks, unless
the time_to_live flag is set.
To get more insight into the delivery of a message:
For Android and iOS: See the FCM reporting dashboard, which records
the number of messages sent and opened on iOS and Android devices,
along with data for "impressions" (notifications seen by users) for
Android apps.
For Android: If you'd like to be notified when the application
successfully receives a message, you can use
delivery_receipt_requested functionality following the guidelines.
This requires you to setup an XMPP server.
For Android, iOS and Web: You can use InstanceID APIs to check the
most recent date that the device you're targeting through the FCM
registration token has established a connection with FCM.
The issue is that I want to send push notifications to iOS and I am able to do it via the token to the specific device and everything is working fine but the issue I am facing is that I only get one one notification if my phone is not connected to internet, when I connect it back to the internet.
Like If I send 5 different notifications to a token via POST Request using Postman and I had turned off my Mobile phone Data and my Wifi and after sometime I turn on any one of them then I only receive the last notification which I request out of the 5.
You should read about 'non-collapsible' messages in the Firebase documentation if you expect to get all messages.
https://firebase.google.com/docs/cloud-messaging/concept-options?authuser=1 clearly states
Except for notification messages, all messages are non-collapsible by default.
Maybe you're sending collapsible messages. And the FCM documentation states that:
If the device is connected but in Doze, a low priority message is
stored by FCM until the device is out of Doze. And that's where the
collapse_key flag plays a role: if there is already a message with the
same collapse key (and registration token) stored and waiting for
delivery, the old message is discarded and the new message takes its
place (that is, the old message is collapsed by the new one). However,
if the collapse key is not set, both the new and old messages are
stored for future delivery.
You can try sending non-collapsible messages.
I'm using AWS SNS for send a push notification to mobile app by subscribe all the device under a single SNS Topic. Then to send notification I just send to that topic.However if some endpoint could not receive a message for whatever reason, SNS will mark that endpoint as disabled.
This could be good if SNS only mark a permanent invalid endpoint, but it's not. Since if I re-enable it, then after next push notification sent its might not back to disable again which mean in the next push it can receive a message properly.
The process to re-enable was quite pain, I have to schedule a batch process to loop all the endpoint under each SNS application and re-enable each device endpoint 1 by 1. This take hours and increasing as device number grow.
How can I know which endpoint was really no longer valid due to user already uninstall an app so I don't have to bother re-enable it?
Or, is there any better way to handle this?
I believe the right solution of the problem is to stop the endpoints from getting disabled in the first place. The strategy should be such that SNS only disable the permanently invalid endpoints such as app uninstalled cases and avoid/recover from other cases.
I was in contact with the AWS support. I came to know about a case where the device token for a device can become invalid and in my case, I had a logic where I was re-enabling the endpoint of the device but using the same invalid token as before. Because of this the endpoint will become enabled but as soon as there is a push done to it, SNS will mark it disabled again since the underlying token is invalid. The right thing to do is to check if the token has changed or not from the device side and when it has pass the token for SNS registration again.
Below is the pseudo code for this strategy:
///////////////////////
retrieve the latest token from the mobile OS
if (endpoint arn not stored)
# first time registration
call CreatePlatformEndpoint
store returned endpoint arn
endif
call GetEndpointAttributes on the endpoint arn
if (getting attributes encountered NotFound exception)
#endpoint was deleted
call CreatePlatformEndpoint
store returned endpoint arn
else
if (token in endpoint does not match latest) or
(GetEndpointAttributes shows endpoint as disabled)
call SetEndpointAttributes to set the
latest token and enable the endpoint
endif
endif
//////////////////////
I'm trying to understand what I will need to build on my server for Push notifications to work successfully.
My thoughts were:
The phone sends the notify URL to my server
The server stores the information in a Database
A separate process or PHP script will query the database and open continuous looping process for each device. (Each socket will be querying a 3rd party API)
When there is a change detected in the API for that device a push notification will be sent to the device's notify url.
Is this the right method on what needs to be done. Isn't this going to eat up server resources or is it the expected outcome of Push a push notifications server?
I've produced a simple diagram on all this below:
First of all, let's separate the process in the main stages needed for PUSH.
Device subscription.
Send the PUSH
Process the notification on device.
Subscription
For the subscription, your device (more specifically, your App) must call the PUSH api,for enabling PUSH notifications. This call to the push API will give you a URL that uniquely identify the device where your application is installed and running. You should store this URL on your database, the same way you store a user's email, or a user's phone number. No special black magic here. You only use it when you need to send a communication to a user.
Send the PUSH
For the push stuff, the same approach as for email, or SMS messaging here: "One does not simply make an infinite loop and send a message if any change is detected". What you have to do is, just send the PUSH message when your application needs to. So you have the user to which you want to send a message, instead of opening a SMTP connection to send ane mail, just build the PUSH XML Message and call the URL associated with that user. Some things to consider here are:
Network reliability (you need to retry if you can't connect to the server).
Response error code-handling (you don't need to retry if the server tells you that the phone has uninstalled your application, for example).
Scalability. You don't want to send a PUSH message from your PHP code, because you don't know how long it will take for the task to be completed. You have to make this thing asynchronously. So just queue up all the push messages, you can create a separate process (windows service, nodeJS service, cron job, daemon, etc.) to send the PUSH, handle retries and errors and clean the queue.
Process the notification on Device
So now that you are this far, you need to handle the notification on the phone. It depends on the type of PUSH notification that you are sending:
Tile. You will update the image, text and counter of the application tile, if the user has put your application to the start screen. On client side you need nothing to so, as all these parameters are part of your PUSH request.
Toast. This one requires a title, text (limited to some 35 characters more or less) and a relative URL inside of your APP. Your application will be launched (like when you click on a Toast notification from Twitter, for example) using the URI that you specify in the payload. So a bit of data can be already injected here. You may/or may not make a request to your server for new data. It is up to you.
Raw. This one is pretty much silent. Is not seen by the user if your APP is not running. As you might guess, this kind of PUSH is useful to live update your running APP, instead of continuously polling your server, wasting user battery and bandwidth and wasting your server resources. You can send anything (raw bytes or strings) up to the max size of the payload allowed my Microsoft.
If yo have any more questions, don't hesitate to ask.
Bottom line: separate the PUSH sending, make it async, don't you ever forget that...
Your PHP script that continually pings the database for changes...THAT is what will eat up your system resources. Push notifications go hand in hand with Event Driven Programming. This means that ideally, your code shouldn't continuously ping your DB. Rather, when something happens (ie, an "event"), THEN your code does something...like contact your phone via push notification.
Your steps for push notifications are more or less correct, but are incomplete. Step 4: the server contacts the client via the notify url (which you have). Step 5 is that the client then contacts the server to actually pull down the information it needs. That is: The new information is not provided to the client via the notify url. Once the client has its new information, then the program continues as normal (populates a list, downloads skynet, etc.)
Your third step is very wasteful and not practical if your app is installed on more than a few devices.
Instead, each device should be subscribed to types of server updates it cares about. Your server's DB will have a mapping from each type of update you support to the list of notification channel URLs of devices that care about this update type.
When your server detects an update of type X, it would send a notification to all devices subscribed to that type of update.
I have an app set up to generate passbook passes. The successfully install on the device and I can do manual (pull-down) updates.
Next I began to implement APNS. I'm using the enhanced request method to connect to the production environment, sending in an empty payload (as required) and it returns no error codes when I request a push notification, but my pass never updates and I see no requests hitting my server. I'm using my own device to test until I can get see an update for myself. No pass updates are received.
I then implemented the Feedback service in the hope that it might tell me something. I noticed this. If I pass in the push token, I receive a response which indicates that the device is not receiving notifications (even though the pass is set for automatic updates). The pass is not updated.
I'd appreciate any info into why the the push notifications do not seem to be arriving.
Thanks.
-Erich
One gotcha to check is that you are not using the sandbox APNS server. All Passbook push requests should be sent to the live APNS server.
Try enabling the additional logging option from the PassKit section of the Developer Settings on your device then connecting your device to Xcode and monitoring the console as you send the push. If the push is received, then you should be able to see your device requesting the serials to be updated from your webservice and you should also see your server's response.
Assuming you send a serial and that it matches the serial installed on your device, you should then see the device requesting the updated .pkpass bundle.
If no push is received, try toggling automatic updates on and off while monitoring the device console. It could be that the device is not receiving a valid registration (201) response or that you are using a stale token - you'll be able to see these via the console.