Firebase Cloud Messaging (FCM) for Android and iOS
The FCM gem lets your ruby backend send notifications to Android and iOS devices via Firebase Cloud Messaging.
Installation
$ gem install fcm
or in your Gemfile
just include it:
gem 'fcm'
Requirements
For Android you will need a device running 2.3 (or newer) that also have the Google Play Store app installed, or an emulator running Android 2.3 with Google APIs. iOS devices are also supported.
A version of supported Ruby, currently:
ruby >= 2.4
Getting Started
To use this gem, you need to instantiate a client with your firebase credentials:
fcm = FCM.new(
GOOGLE_APPLICATION_CREDENTIALS_PATH,
FIREBASE_PROJECT_ID
)
About the GOOGLE_APPLICATION_CREDENTIALS_PATH
The GOOGLE_APPLICATION_CREDENTIALS_PATH
is meant to contain your firebase credentials.
The easiest way to provide them is to pass here an absolute path to a file with your credentials:
fcm = FCM.new(
'/path/to/credentials.json',
FIREBASE_PROJECT_ID
)
As per their secret nature, you might not want to have them in your repository. In that case, another supported solution is to pass a StringIO
that contains your credentials:
fcm = FCM.new(
StringIO.new(ENV.fetch('FIREBASE_CREDENTIALS')),
FIREBASE_PROJECT_ID
)
Usage
HTTP v1 API
To migrate to HTTP v1 see: https://firebase.google.com/docs/cloud-messaging/migrate-v1
fcm = FCM.new(
GOOGLE_APPLICATION_CREDENTIALS_PATH,
FIREBASE_PROJECT_ID
)
= {
'token': "000iddqd", # send to a specific device
# 'topic': "yourTopic",
# 'condition': "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)",
'data': {
payload: {
data: {
id: 1
}
}.to_json
},
'notification': {
title: notification.title_th,
body: notification.body_th,
},
'android': {},
'apns': {
payload: {
aps: {
sound: "default",
category: "#{Time.zone.now.to_i}"
}
}
},
'fcm_options': {
analytics_label: 'Label'
}
}
fcm.send_v1() # or fcm.send_notification_v1(message)
Device Group Messaging
With device group messaging, you can send a single message to multiple instance of an app running on devices belonging to a group. Typically, "group" refers a set of different devices that belong to a single user. However, a group could also represent a set of devices where the app instance functions in a highly correlated manner. To use this feature, you will first need an initialised FCM
class.
The maximum number of members allowed for a notification key is 20. https://firebase.google.com/docs/cloud-messaging/android/device-group#managing_device_groups
Generate a Notification Key for device group
Then you will need a notification key which you can create for a particular key_name
which needs to be uniquely named per app in case you have multiple apps for the same project_id
. This ensures that notifications only go to the intended target app. The create
method will do this and return the token notification_key
, that represents the device group, in the response:
project_id
is the SENDER_ID in your cloud settings.
https://firebase.google.com/docs/cloud-messaging/concept-options#senderid
params = { key_name: "appUser-Chris",
project_id: "my_project_id",
registration_ids: ["4", "8", "15", "16", "23", "42"] }
response = fcm.create(*params.values)
Send to Notification device group
To send messages to device groups, use the HTTP v1 API, Sending messages to a device group is very similar to sending messages to an individual device, using the same method to authorize send requests. Set the token field to the group notification key
= {
'token': "NOTIFICATION_KEY", # send to a device group
# ...data
}
fcm.send_v1()
Add/Remove Registration Tokens
You can also add/remove registration Tokens to/from a particular notification_key
of some project_id
. For example:
params = { key_name: "appUser-Chris",
project_id: "my_project_id",
notification_key:"appUser-Chris-key",
registration_ids:["7", "3"] }
response = fcm.add(*params.values)
params = { key_name: "appUser-Chris",
project_id: "my_project_id",
notification_key:"appUser-Chris-key",
registration_ids:["8", "15"] }
response = fcm.remove(*params.values)
Send Messages to Topics
FCM topic messaging allows your app server to send a message to multiple devices that have opted in to a particular topic. Based on the publish/subscribe model, one app instance can be subscribed to no more than 2000 topics. Sending to a topic is very similar to sending to an individual device or to a user group, in the sense that you can use the fcm.send_v1
method where the topic
matches the regular expression "/topics/[a-zA-Z0-9-_.~%]+"
:
= {
'topic': "yourTopic", # send to a device group
# ...data
}
fcm.send_v1()
Or you can use the fcm.send_to_topic
helper:
response = fcm.send_to_topic("yourTopic",
notification: { body: "This is a FCM Topic Message!"} )
Send Messages to Topics with Conditions
FCM topic condition messaging to send a message to a combination of topics, specify a condition, which is a boolean expression that specifies the target topics.
= {
'condition': "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)", # send to topic condition
# ...data
}
fcm.send_v1()
Or you can use the fcm.send_to_topic_condition
helper:
response = fcm.send_to_topic_condition(
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)",
notification: {
body: "This is an FCM Topic Message sent to a condition!"
}
)
Sending to Multiple Topics
To send to combinations of multiple topics, require that you set a condition key to a boolean condition that specifies the target topics. For example, to send messages to devices that subscribed to TopicA and either TopicB or TopicC:
'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)
FCM first evaluates any conditions in parentheses, and then evaluates the expression from left to right. In the above expression, a user subscribed to any single topic does not receive the message. Likewise, a user who does not subscribe to TopicA does not receive the message. These combinations do receive it:
- TopicA and TopicB
- TopicA and TopicC
You can include up to five topics in your conditional expression, and parentheses are supported. Supported operators: &&
, ||
, !
. Note the usage for !:
!('TopicA' in topics)
With this expression, any app instances that are not subscribed to TopicA, including app instances that are not subscribed to any topic, receive the message.
The send_to_topic_condition
method within this library allows you to specicy a condition of multiple topics to which to send to the data payload.
response = fcm.send_to_topic_condition(
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)",
notification: {
body: "This is an FCM Topic Message sent to a condition!"
}
)
Subscribe the client app to a topic
Given a registration token and a topic name, you can add the token to the topic using the Google Instance ID server API.
topic = "YourTopic"
registration_token= "12" # a client registration token
response = fcm.topic_subscription(topic, registration_token)
# or unsubscription
response = fcm.topic_unsubscription(topic, registration_token)
Or you can manage relationship maps for multiple app instances Google Instance ID server API. Manage relationship
topic = "YourTopic"
registration_tokens= ["4", "8", "15", "16", "23", "42"] # an array of one or more client registration tokens
response = fcm.batch_topic_subscription(topic, registration_tokens)
# or unsubscription
response = fcm.batch_topic_unsubscription(topic, registration_tokens)
Get Information about the Instance ID
Given a registration token, you can retrieve information about the token using the Google Instance ID server API.
registration_token= "12" # a client registration token
response = fcm.get_instance_id_info(registration_token)
To get detailed information about the instance ID, you can pass an optional
options
hash to the get_instance_id_info
method:
registration_token= "12" # a client registration token
= { "details" => true }
response = fcm.get_instance_id_info(registration_token, )
Mobile Clients
You can find a guide to implement an Android Client app to receive notifications here: Set up a FCM Client App on Android.
The guide to set up an iOS app to get notifications is here: Setting up a FCM Client App on iOS.
ChangeLog
2.0.0
Breaking Changes
- Remove deprecated
API_KEY
- Remove deprecated
send
method - Remove deprecated
send_with_notification_key
method - Remove
subscribe_instance_id_to_topic
method - Remove
unsubscribe_instance_id_from_topic
method - Remove
batch_subscribe_instance_ids_to_topic
method - Remove
batch_unsubscribe_instance_ids_from_topic
method
Supported Features
- Add HTTP v1 API support for
send_to_topic_condition
method - Add HTTP v1 API support for
send_to_topic
method
1.0.8
- caches calls to
Google::Auth::ServiceAccountCredentials
#103 - Allow
faraday
versions from 1 up to 2 #101
1.0.7
- Fix passing
DEFAULT_TIMEOUT
tofaraday
#96 - Fix issue with
get_instance_id_info
option params #98 - Accept any IO object for credentials #95
Huge thanks to @excid3 @jsparling @jensljungblad
1.0.3
- Fix overly strict faraday dependency
1.0.2
- Bug fix: retrieve notification key" params: https://github.com/spacialdb/fcm/commit/b328a75c11d779a06d0ceda83527e26aa0495774
1.0.0
- Bumped supported ruby to
>= 2.4
- Fix deprecation warnings from
faraday
by changing dependency version tofaraday 1.0.0
0.0.7
- replace
httparty
withfaraday
0.0.2
- Fixed group messaging url.
- Added API to
recover_notification_key
.
0.0.1
- Initial version.
MIT License
- Copyright (c) 2016 Kashif Rasul and Shoaib Burq. See LICENSE.txt for details.
Many thanks to all the contributors
Cutting a release
Update version in fcm.gemspec
with VERSION
and update README.md
## ChangeLog
section.
# set the version
# VERSION="1.0.7"
gem build fcm.gemspec
git tag -a v${VERSION} -m "Releasing version v${VERSION}"
git push origin --tags
gem push fcm-${VERSION}.gem