Parse push notification android device token not saved in some cases - android

I am using parse as my app back-end service provider. My app has really important feature of Push notification.
Parse is not saving the device token in some cases. Mostly when user is installing the app from America/Los_Angeles region.
Is this Parse.com sdk integration problem or Google is not sending device token in some region? How can i fix this issue?

I've just ran a quick check on our Parse backend and found that there are also missing device tokens in our database, too.
I think you should not send push notifications based on device token, but based on user on that device.
To do that, first add a new field in Installations table called user. If your app requires explicit login from user, then when user logs in, update the installation with that user's ID. If it is implicit (registers upon installation so App is ready to go as soon as user opens the app), then just associate that user in the same manner on app install.
In the end, you are most likely to want to send your notifications to your user rather than a specific device. This also makes data transferring a lot easier.

This issue was sometimes observed due to failure to get the token from Google. You should check the device token availability, if you don't get it, you should try it again after some time from your app.

Related

Firebase: Add device token ID to all old users

I have published an android app that uses Firestore for the database. Now, I want to enable push notifications.
I have figured out I need to attache a device token id for each user to send notification to a specific device. The problem is that I have lots of old users! Is there anyway to add token id for each one instead of waiting for all users to upgrade the app?
The only way you can collect device tokens is from the device itself. So, your users will have to upgrade their app to version that collects the tokens, associates it with the user, and writes it to Firestore.

Can i disable push notifications via Firebase?

I am implementing push notification in my app after having it for IOS for a while.
Use case: I have user login, and accounts stored on our servers. I only want to send push notifications when a user is logged in, and only for the user currently logged in. Notifications are targeted to the individual user.
To do this, i fetch the token using
FirebaseInstanceId.getInstance().getToken()
, send push token to our server when user logs in, and remove it on logout.
Everything works as far as registering token, sending the token etc., HOWEVER, there could be scenarios where this doesn't work, for example if a user logs out with flight mode, so our server still has the token and thinks it should still send them.
On IOS, there are two local functions, register/unregisterforremotenotifications, that basically turns notifications on/off, regardless of whether my server could be contacted. I can call these on login/logout, and IOS won't show any remote notifications for my app, and i'm safe.
However, with Firebase, i can send the token to the server on login -
for logout, however, its more complex since there's no "local" system-function to call that i can find.
The best thing i've figured out, is to always send a 'Data' notification,
as described in this question,
so that my notification service always gets called, even in the background, and there check if i am logged in, and not show the notification if i'm not.
However, the notification for the wrong user will still be sent to the phone, and it's a risk, for example if i, god forbid would have a bug... or the notification gets logged somewhere in the system.
Sooo, my question is if there's any way to disable notifications on logout via Firebase?
I hope this makes sense, thoughts much appreciated!
Yes, what you do is you create your own Login and Logout APIs.
In your Login you should be storing your Token for PUSH notifications.
then whatever data triggers need to PUSH do a loop and build a push for known registered tokens.
On logout, simply delete that token from your Database and the loop will no longer include it for PUSH. You are correct using DATA tag will only work in foreground, but could be for wrong user that is correct.
If you do not have a backend, then please provide more clarity as to where/how you are storing and using your tokens to PUSH so I can help you further.
I have done this exact scenario to avoid wrong person getting push, but I support foreground and background on my scenario, so only logout or expired token will disable the PUSH on my app.
There are two ways:-
Your app supports multi user login at the same time scenarios :-
You can probably store the device token in share preferences with a boolean flag , when user relaunch the app , check if the flag for deletion is set then you can try deregistering from the service on server.
If it fails then again you can do the same , so it would be something like checking boolean flag for account deletion on every app launch to make sure it deregister.
Your app supports single usr:-
You can simply delete firebase instance Id before signing into the account. This would take care of the scenario where a different user had signed out offline and you were not able to de register from your service.
You can also handle scenarios when to show notification based on accountId or user Id of the signed in user.

android - when to do GCM registration

I have a android client app, a server side in django and now I am adding push notifications with GCM.
In my app I have users that login/logout, so I will have a table in my database with devices ids coupled with users, so that every time I want to notification a user, I will lookup its device id and send the notification.
my question is:
When is best to register the Device to the GCM?
When to add the Device to my Server side database?
In the Google Docs it says you should do it once, when the app is installed.
Because I have users in my app, and I want to couple a user with a device in the database, when the app is installed there still isn't a user to associate the Device with.
After the user installs the app, he can register, login and so on.
So when you think is best to register the Device to the GCM and to my server side?
Should it be with a user or only associate it later?
Thanks a lot!
My suggestion would be:
Register the device immediately after the first execution
Save device id somewhere accessible anytime by the app
Couple the id with user details after registration
With this approach you will be able to handle issues if something goes wrong with the registration process and send a notification to the device even if the user is not registered.
EDIT:
You should also implement a strategy to check on a regular basis if the association between the user and the device is still valid or needs to be updated

How should I handle authentication when my mobile apps report their device tokens to my server?

I have an app that runs across iOS and Android. I'm working to add push notifications to that app.
At a very high level, devices register with the Apple Push Notification Service (APNS) or Google Cloud Messaging (GCM) and receive a token. They then hand that token back to the server that's in charge of sending notifications. That server, when it wants to, sends a notification to APNS or GCM and says "send this notification to the devices with these tokens".
So, my apps need to be able to securely send their tokens to my server, and delete those tokens from the server when the user no longer wants to receive notifications. It's very easy to add a simple CRUD page on the server side which handles ?create=<token>, ?delete=<token>, etc.
But what happens when someone goes to my server and starts spamming random values for ?delete=<token> — it seems like they'd be able to just delete random device tokens at will?
I've thought about the "delete" case a bit more, and I think it should be easy: the app can just send along a generated public decryption key with the initial “create this token” request. That key can be stored against the token. When the app wants to delete, it can send along the encrypted copy of the token, and the server can match the token against the decrypted copy, verifying that the app must possess the stored public keys matching private encryption key (which is a secret known only to the app).
What happens when someone starts spamming random values for ?create=<token> — do they get to just fill up my database table with fake device tokens?
I can't see an easy answer — rate limiting "create" requests from any single IP address seems to be about the best we can do without registration involved. That obviously isn't going to help us against any distributed attack.
Ideally I'd like to enable push notifications by default / without the user having to "register" or anything like that. My first thought is that each device token should be tied to a known canonical Apple ID or Google account — but how do I stop users from falsifying those? Do devices come with a certificate that I can get an authoritative public key for (in which case each device can just get a row tied to its public key)? What's the best way for me to implement authentication here?
The solution to the problem for android can be found Here. In brief it can be summarised as
You use the GoogleAuthUtil class, available through Google Play
services, to retrieve a string called an “ID Token”. You send the
token to your back end and your back end can use it to quickly and
cheaply verify which app sent it and who was using the app.
A lot of good questions here. :)
Let me try to break it down.
General thoughts
I don't think it's good idea to mix Android and iOS here. High level push notification architecture is similar between them, but that's about it.
Tokens are long (as I remember iOS token is uuid). So, there is no way to guess it by just randomly trying different values. So, I would say ?delete=<token> case is non existent.
The case of ?create=<token> is more realistic. First of all, somebody can bring your server to knees, registering millions of tokens. Also, if you are sending some sensitive information via push notification, you may don't want it to be received by non authorized app users.
Android solution
For Android it's easier.
As soon as you get a token on the server, just send a push message with some randomly generated string (store it in DB). Your application on a device will get this string and will send it with the token to the server (via second web call). And your server make sure that it will send anything to this token only after it was authenticated.
This way you rely on GCM ability to deliver messages to correct clients to make sure that authentication information (random string) is delivered to your application.
iOS solution
The problem with iOS is that push notification doesn't automatically trigger code execution, if the application is suspended or in background.
So, if you will try to do the same thing and a user accidentally exits your app, while push notification is being deliver than your app will never see it.
You can do following (the idea is basically the same as for Android, only with difference that we may need to require user interaction)
Push notification with a message "Please run my app and enter X" (where X is some random string)
This way, if your app is in background, a user will click on this message, enter X and your app will authenticated to the server.
In the case, if app is in foreground, it will get push payload and can authenticate directly.

Why do I get multiple active Tokens for my Device with Googles Cloud To Device Messaging Service?

I just added C2DM capability to my Android App.
At the moment the following happens if C2DM is started in my App.
My App sends the registration Intent
The answer broadcast is received by my app
The device token is retrieved from the intent and sent to my server
From that moment everything is working fine. The client receives the push notifications etc.
A problem occurs if the following hapens:
The user uninstalls the application without disabling push. (Completely deleting it not only updating)
The user reinstalls the application
If after step 5 a push notification is sent my app still receives this notification.
It seems that the token which was retrieved from the previous install is still active and is reconnected to the new instance of my application.
This leeds to the following problem:
A user who reinstalls my app but has no intention of receiving push notifications has no possibility to remove himself from the service because the new instance of the app has no way to unregister the old token from my server.
Is this a bug in the C2DM system or is something wrong in my setup?
Update
I followed Berdons advice and did the following:
For testing purposes only start an unregister Intent every time my app starts up.
After I send the unregister intent no push notification from my server is sent to my application. That seems to do the trick, but if I now go the C2DM Settings Screen and turn on push notifications for my app all the old tokens get active again and I receive information that I did not register for in the current installation of my app.
Next Update
It seems I'm not the only one with this problem:
Android C2DM : Duplicate message to the same device and App
I hoped that Google would manage those tokens in a way that old tokens from the same device get disabled after a new one was issued. I also expect that after I sent an unregister Intent all tokens for that application and that device are marked as invalid or deleted from the Google Server for ever. If this is somehow a design decision by Google for special use cases I don't see please enlighten me.
We now found a solution that should work in most of the cases.
The server adds the C2DM registration id as a data field with every C2D Message.
The device now only shows a notification if the token in the message and the token that is stored in a pref file match. That way we guarantee that we don't show messages for device tokens that were obtained by previous installs.
If the tokens do not match we found an old token that should not be active anymore. We now mark the token on our own web server as inactive to prevent the server from sending more unnecessary C2D Messages
This solution enables us to show only relevant data without the need to store a unique user id.
In my C2DM implementation, each user's device token is saved in a database against their UDID and the package name of the app (among other things). The UDID and package name form the primary key, meaning that the table can list multiple apps from the same device (UDID). When a user runs a particular app, the device token is recorded, and if they uninstall and re-run the app, the new device token would be recorded over the old one. We also have columns to record whether push is active for that particular app/device combo, and which types of push messages the user has enabled/disabled.
When the time comes to send a push for a particular app, no UDID will be registered more than once (since these two fields form the primary key), and therefore only the latest device token will be used. Furthermore, our query only returns the rows that have push messages enabled.
This solution should solve your problem because it prevents you from sending the push to both device tokens. I hope this helps!
More like an unexpected "feature". You might consider issuing an unregister request on the "first run" (first run ever) of your application to prevent this from occuring.
Update
You could could do the work of differentiating between different C2DM messages by using the collapse_key (or anything of your own creation) as an identifier. Update it between registrations and pass it to the device following registrations, unregistrations and messages.

Categories

Resources