I have a single android application, which supports for 7 countries(Localization and Internationalization). The application functionality and language changed based on the device locale.
I need to implement the GCM push notifications for this application.
Requirement:
Is it possible to send the push notification in 7 different languages with single GCM account.
Is there any way to display the push notification in their device local language.
You can either take the approach suggested by Ascorbin, or implement something similar to what Apple have in their push notifications:
Your server can send a GCM message with a parameter that is a key to a message. Yout Android App will have to contain for each possible key the strings that should be displayed for it in each of the 7 languages (using multiple copies of strings.xml). Then the GCM reciever in your app will get the key from the server and get the resource string that matches it (it will automatically get the string that matched the locale of the device). This way you don't have to worry about localization in your server. The downside of this approach is that all your messages have to be predefined in your app.
You can also add parameters to the message key like Apple do.
For example, the server sends a key = "NEW_MAIL_FROM" and param1 = "John". The app finds a string resource for that key (lets assume the device used English locale) - "You have a message from {0}" - and replaces the param with John, displaying the message "You have a message from John". A device with a differennt locale will show a message in a different language.
You can implement that server-side, after GCM registration with the send of token, send also the device locale. And then notify users instantly with a localized message.
Payload is something "sort" its not a good idea to pass through it so much information.
On the other hand if you have fixed messages you can use:
private void handleMessage(Intent intent) {
// server sent key-value pairs
String name_of_resource = intent.getExtra("message_id");
int id = getResources().getIdentifier(name_of_resource, "string", getPackageName());
if (id != 0) {
String text = getString(id); // the text to display
// generates a system notification to display here
}
}
see http://developer.android.com/google/gcm/gcm.html#received_data for handling received data.
When the devices register at your server, let them send the Locale. So you can have locale groups of devices and send the messages in according languages.
You can easily localize your GCM notification using title_loc_key and body_loc_key. These keys listed in official GCM docs.
More details can be found here.
Send a GCM Push from server (without any language specific data).
In response to the push, the client makes a REST api call to the server with it's language as a Query parameter.
The server fetches appropriate language's text and send back to the client on real time.
Related
I want to be able to add more than one sender id in my android app.
From https://developers.google.com/cloud-messaging/concept-options
GCM allows multiple parties to send messages to the same client app. For example, suppose the client app is an articles aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article. Instead of having to centralize all sending activity in one location, GCM gives you the ability to let each of these contributors send its own messages.
How is this achieved using google-services.json configuration file?
UPDATE: Going to refer to the official and recommended way in doing this instead of the hacky and unofficial approach to prevent/avoid unknown problems. From my answer here.
There is actually a part in the documentation about this topic:
Receiving messages from multiple senders
FCM allows multiple parties to send messages to the same client app. For example, suppose the client app is an article aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article. Instead of having to centralize all sending activity in one location, FCM gives you the ability to let each of these contributors send its own messages.
To make this possible, make sure each sender generates its own sender ID. See the client documentation for your platform for information on on how to obtain the FCM sender ID. When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field.
Finally, share the registration token with the corresponding app servers (to complete the FCM registration client/server handshake), and they'll be able to send messages to the client app using their own authentication keys.
Note that there is limit of 100 multiple senders.
I think the confusing but important part here is:
When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field.
In other terms, you'll have to call getToken() passing the Sender ID and simply "FCM" (e.g. getToken("2xxxxx3344", "FCM")) as the parameters. You'll have to make sure that you call this for each sender (project) that you need.
Also, note from the getToken() docs:
This is a blocking function so do not call it on the main thread.
Some additional good-to-knows:
It does not auto retry if it fails like the default one.
It returns an IOException when it fails.
As of Dec. 2016, there's a very simple, non-hacky way to do this, which still works now (Jul 2018).
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("1:something:android:something_else") // Required for Analytics.
.setApiKey("your apikey") // Required for Auth.
.setDatabaseUrl("https://your-database.firebaseio.com/") // Required for RTDB.
.build();
FirebaseApp.initializeApp(this /* Context */, options, "secondary");
Source: The official Firebase blog
Comma seperated senderID solution is still working and able to register same token for 2 different sender. I sent push notif to that single magical token with using 2 different api key and able to receive push notifs for both api key. Hope it works at least till the end of 2020. Because I'm trying to make a seamless transition between an old GCM and FCM projects which targets more than 1 million user. (hear me google and thank you google for not deprecating this great solution)
String magicalToken = FirebaseInstanceId.getInstance().getToken("senderId, anotherSenderId", "FCM");
You can get the single token for multiple sender by passing them as comma separated string and then these sender will be able to send the push notification using the common token, try calling
FirebaseInstanceId.getInstance() .getToken("senderId1,senderId2",
FirebaseMessaging.INSTANCE_ID_SCOPE);
make sure you call this from a background thread.
I want to be able to add more than one sender id in my android app.
From https://developers.google.com/cloud-messaging/concept-options
GCM allows multiple parties to send messages to the same client app. For example, suppose the client app is an articles aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article. Instead of having to centralize all sending activity in one location, GCM gives you the ability to let each of these contributors send its own messages.
How is this achieved using google-services.json configuration file?
UPDATE: Going to refer to the official and recommended way in doing this instead of the hacky and unofficial approach to prevent/avoid unknown problems. From my answer here.
There is actually a part in the documentation about this topic:
Receiving messages from multiple senders
FCM allows multiple parties to send messages to the same client app. For example, suppose the client app is an article aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article. Instead of having to centralize all sending activity in one location, FCM gives you the ability to let each of these contributors send its own messages.
To make this possible, make sure each sender generates its own sender ID. See the client documentation for your platform for information on on how to obtain the FCM sender ID. When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field.
Finally, share the registration token with the corresponding app servers (to complete the FCM registration client/server handshake), and they'll be able to send messages to the client app using their own authentication keys.
Note that there is limit of 100 multiple senders.
I think the confusing but important part here is:
When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field.
In other terms, you'll have to call getToken() passing the Sender ID and simply "FCM" (e.g. getToken("2xxxxx3344", "FCM")) as the parameters. You'll have to make sure that you call this for each sender (project) that you need.
Also, note from the getToken() docs:
This is a blocking function so do not call it on the main thread.
Some additional good-to-knows:
It does not auto retry if it fails like the default one.
It returns an IOException when it fails.
As of Dec. 2016, there's a very simple, non-hacky way to do this, which still works now (Jul 2018).
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("1:something:android:something_else") // Required for Analytics.
.setApiKey("your apikey") // Required for Auth.
.setDatabaseUrl("https://your-database.firebaseio.com/") // Required for RTDB.
.build();
FirebaseApp.initializeApp(this /* Context */, options, "secondary");
Source: The official Firebase blog
Comma seperated senderID solution is still working and able to register same token for 2 different sender. I sent push notif to that single magical token with using 2 different api key and able to receive push notifs for both api key. Hope it works at least till the end of 2020. Because I'm trying to make a seamless transition between an old GCM and FCM projects which targets more than 1 million user. (hear me google and thank you google for not deprecating this great solution)
String magicalToken = FirebaseInstanceId.getInstance().getToken("senderId, anotherSenderId", "FCM");
You can get the single token for multiple sender by passing them as comma separated string and then these sender will be able to send the push notification using the common token, try calling
FirebaseInstanceId.getInstance() .getToken("senderId1,senderId2",
FirebaseMessaging.INSTANCE_ID_SCOPE);
make sure you call this from a background thread.
I'm building a system which has following requirements:
Client device registers with Server & REGID is saved. Ex. 12 (ID) & the n system user can send a notification to the selected REGIDs or REGID depending upon requirement.
Possibility of attaching files or images (Optional)
I'm confused to go for GCM or build custom code for my requirements, the most apt thing I found was GCM Topic Messaging.
And the 2nd thing is totally optional.
I'd love to hear some suggestions.
you can use parse (parse.com) and create channel per user or ID user and send GCM messages, images, text, etc for x channels... on the format CLASS-ID_PEOPLE.
My team has been developing an app using GCM for the last 4 months, and today we discovered that with the recent update of Google Play Services GCM changed significantly. Until now we've been sending notifications from our backend server to our users using this format of Registration ID:
APA91bF7h6vQkqIaF9ECQ_V............w
That was generated with the classic GoogleCloudMessaging.getInstance(context).register(SENDER_ID) method.
But now, with the new update, you generate the registration ID doing InstanceID.getInstance(this)getToken(SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
and by doing so the generated Registration IDs have the next format:
c3wlROAji5d:APA91bF_iz3Muub6Mu...a6n-ClpQ
Notice how there is first a section of 11 characters followed by a colon and then a long sequence starting with APA91b
So my question is, when sending notifications from my server to my clients should I use the new format as it is or strip the fragment before the colon and use the segment starting with APA91b as before.
Thanks for the attention
You should always use the full registration id to send messages to your users: it is best to think of the registration id as a totally opaque string (i.e., internal structure does not necessarily mean anything).
my question is the same as this one:
android device specific push notifications by using azure mobile services
But I'm using .Net backend. This is the part where I send the notification:
Dictionary<string, string> data = new Dictionary<string, string>() { { "message", "this is the message" } };
GooglePushMessage message = new GooglePushMessage(data, TimeSpan.FromHours(1));
Services.Push.SendAsync(message);
but there is no way to pass in the registration ID.
UPDATE
I've also tried using the payload property of GooglePushMessage:
GooglePushMessage message = new GooglePushMessage();
message.JsonPayload = JsonConvert.SerializeObject(new { registration_id = "blablabla", data = new { message = "77" } });
It turns out that it is ignoring the registration_id property, because I'm still getting the notification on my device.
What I want to achieve is to get API calls from third parties and use the registration ids that I have stored in my DB to send notifications to specific devices.
Mobile Services uses Notification Hubs to handle it's push notifications. Notification Hubs filters push (i.e. does targeted push to specific devices, users, etc) using a Tag system. So if you want to be able to push to a specific Android Registration ID, when the device registers for Push Notifications with your Mobile Service, you should specify tags that you want to tie your registration to like so:
ToDoActivity.mClient.getPush().register(gcmRegistrationId, "tag1", "tag2");
If you want to push based off of the registration ID, you'd use that ID as one of your tags. Then from your .NET backend, when you call SendAsync, you can specify a tag (or tag expression) to target a specific device. So our call to push becomes:
Services.Push.SendAsync(message, registrationID);
The above text was incorrect. Tags are limited to 120 characters (https://msdn.microsoft.com/en-us/library/dn530749.aspx) and the GCM registration ID is too long for this. TODAY you're stuck with using an alternate tag that is less than 120 characters. If you have a UserID that is known on the device you could use that as a tag and then from your backend you can push to that specific User ID. Alternatively, you could generate a GUID on app launch and use that as a tag and then from your backend push to that GUID whenever you wanted to reach the specific device.