Should I make the call each time a user enters the main activity or should I only make it when the user first installs the app?
startService(new Intent(this, RegistrationIntentService.class))
Essentially the RegistartionIntentService will do the same action (register your app to google's SNS server using the token your app acquired) so it's pretty much usless to do it every time, I'd say you should do it only once after the first time the app has opened.
In order to send push notifications to a device, you need the registration token that is generated by your app when you run your registration service. What you do with that token after you register the device is up to you.
What I do is, when my user logs into my app, I run my GCM registration service which for me, generates a token and then sends that token (along with the logged in user information) to my backend database. From that point forward, my backend code knows the user has registered their device and whenever I need to send them a push, I know to send it with that token.
When the user logs out, I once again make an API call to my backend database which deletes the GCM registration token (you don't have to but its how I do it.)
The point is, once you get that token with your registration service, what you do with it is your responsibility. Save it, store it, etc. You only need to get it once - then you can send all the pushes you want.
Related
Imagine a users installs and opens my app. A FCM Registration token is generated and sent to my server. Later, say the user clears my app's data. When he then opens the app, a new Token will be generated. So, since there's no way for me to know this yet, I send notifications as normal to the old Registration too. Now :
Will FCM assume that the device is offline and keep trying to send the notification until the end of its lifetime (default 4 weeks) ?
If not, how long till it returns registration-token-not-registered error?
No. The FCM servers will know that the token is expired immediately.
From #1, it will send it back immediately.
The thing that might get confusing here is the steps on where you'd actually receive the NotRegistered error. Here's are two possible scenarios:
Device installed the app. Token is generated and sent to your server.
You send a push notification to the token.
FCM server checks, token is still valid, enqueues the message to be sent as soon as feasible.
Next one is from your scenario:
Device installed the app. Token is generated and sent to your server.
User goes offline and clears app data. Previous token is now invalid, but the InstanceID service is not yet informed of it since the device is offline.
You send a push notification to the token. FCM sees that token as valid, sends you back a success response and enqueues the message to be sent as soon as feasible.
Here, the token is currently still currently valid. So you'd receive a success response like usual.
Device goes online. InstanceID service syncs, lets it know that the old token is now invalid and requests for a new one. New token gets generated.
5 Almost at the same time that the device goes online, FCM checks if the token is still valid. If not, then it will drop the enqueued messages.
The thing to always remember is that FCM is working as a middle-man. Hope this clears things up. Cheers!
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.
I want to store FCM token in my android app user's table in database when user register to the app . When i want to send notification to specific user then i will fetch Token from corresponding row and send push notification.But i am confused that whenever app user logout from his app and register new account from same device ,then there will be two row and hence two Token for same device on database. How to handle such case? What happen to old Token in device? please anyone can help me??
The Instance ID token used to send FCM messages represents the instance of and app on a device. The current user of the app would not affect the token that represents the app instance. Uninstalling and reinstalling the app would cause a new token to be generated but not for in app behaviour like switching users.
You should still remove the mapping of the token to the user on logout and add a new mapping with the same token to the user that logs in but it will be the same token.
I probably feel this may help you,
When user logs out clear his device token and make him Logout so that he won't be able to receive the updates and hence only one user at a time can get the updates
I created a Push Notification Server (PNS) by using Google Cloud Messaging (GCM).
With this architecture, my server has to know the token associated to a user in order to send him push notifications.
I extended the class InstanceIDListenerService which is correctly notified when a token has been refreshed (I tested it with adb). When its method onTokenRefresh() is called I take the new token and, so far, all is ok.
My problem is the following: what if I fail to send this new token to my server? (a network error, a lack of connection, a sudden device shutdown, or something else...).
Do I have to store somewhere (preferences?) that server does not know my new token and retry when possible? Is there a way to let the OS to perform this operation?
You may use GCM NetworkManager to queue, schedule, check network connections and... , its very reliable and useful, it handles all of your desired tasks.
Also you have to save your token some where is your device, may be on your shared preferences, till you make sure your server recives it. Please note that if you want to use other features of GCM like topic messaging, you have to save and use token for all topic registrations.
Your app (when it runs) should always check if the token has been sent to the server. When onTokenRefresh is called you should generate and send a new token to the server. If sending the token to the server fails then the next time your app runs it should try again.
You are correct that if you fail to send the token to the server onTokenRefresh your app will not receive notifications till it is run again and successfully sends the token to the server.
Also note that token refresh should not be a regular occurrence. It should only happen for example when the app is uninstalled and reinstalled or the token is deemed to be no longer secure.
I'm developing an application that uses C2DM to receive push notifications. I've implemented the whole C2DM circuit (both client and server) and it's working fine.
Currently my applicacion has a button to bootstrap the C2DM registration, when receiving the registration id token from Google I call a webservice in my app server to associate the device with the registration id.
I'm going to implement authentication in my application and I have a few question related to the handling of the C2DM registration.
The client application (ie the Android one) will have a login screen as the first screen so the user can enter the credentials. As soon as the credentials get validated I'm planning on calling the C2DM registration so the user gets associated with a registration id token. Is this ok? In later executions of the application I will probably store the credentials or some sort of token so the user doesn't need to enter the credentials again, Should I also fire the C2DM registration when the application launches?
I'm aware that Google may eventually update the registration id. Is it a good practice to also update the registration id on a regular basis? If so, when should be appropiate? Does the registration id token expire?
What happens in the rare case of a desynchronization of the registration id between the client and the server (eg a new registration id arrives at the client, in the middle of that a new event is fired on the server with the old registration id, then the registration id arrives at the server)? Will Google handle this cases? Should my app server handle this cases?
What happens if the server is not reachable when a new registration id arrives from Google? Should I backoff and schedule an Alarm to try again?
Can you think of any other pitfalls with this?
1) I would fire the C2DM registration as soon as possible. Nothing in particular, but since the request is asynchronous, firing it up early will help me get the reg ID sooner. However, no need to fire the registration each time the app starts. Once is sufficient.
2) Whenever Google decides to update the reg ID it will send it to the device and you need to do the same steps you followed when you receive the reg id for the first time i.e. convey it to the server.
3 & 4) You may want to go through this documentation. It stresses the fact that you need to make it sure that you send the registration ID to your server and keep on trying. I assume here that if the reg ID is refreshed, and your server still has the old ID, it will not be able to send messages to the device. It will receive a 200OK with an Error Code of InvalidRegistration which means a (missing or) bad registration id.
5) Cannot comment much - would say that it depends on the design of your application. But one thing worth noting is that C2DM is still in Beta so expect things to be different in the long run.
Try to prompt the user with a choice of google accounts that are already on the phone. The http://code.google.com/p/chrometophone/source/checkout shows this. Look at SetupActivity.java for getGoogleAccounts(), etc.