Set up FCM

Last updated 4 months ago

In the last section, Getting Started, you learnt how to successfully setup the Mitter Android SDK and was able to send a message across a newly created channel. It’s time to step up.

Enabling push messaging

In this section, you’ll see how you can get FCM to work with the SDK to receive new messages in real-time via the Push approach we talked about in the last section.

Integrating FCM with your app

First of all, you need to setup FCM in your Android project. The steps for this setup is beyond the scope of this documentation and since Google has done a pretty good job explaining the same, why don’t you go check out their docs if you haven’t already added FCM to your project.

After you’re through with that, the only thing’s that left is to feed your FCM server key in your Mitter.io application inside the Dashboard.

You can do that by following these steps:

  • Open up Mitter Dashboard and select your application from the list

  • Go to the Properties tab

  • Click on New Property -> Google -> FCM -> FCM Property

  • You’ll get a modal where you need to fill out your app’s instance ID which can be easily retrieved from the Google Cloud Console

  • Also, you need to feed in your FCM server key, which can be accessed from your FCM admin panel

  • After you’re done feeding these data, click on New FCM Configuration Property

That’s it, Mitter.io can now get your messages delivered to your users in real-time.

Registering a delivery endpoint

Think of a Delivery Endpoint as an address for your app. By registering your delivery endpoint you’re telling Mitter.io to forward any message that might be of your concern to the device where your app is installed.

Let’s see how you can do that with the SDK. The process is pretty straightforward.

Once you’re done setting up FCM in your project you should have your custom implementation of FirebaseMessagingService as something like MyFirebaseMessagingService or whatever name you chose for your implementation during the setup.

In that class, you need to override a method called onNewToken() and get a reference to the Mitter object from your Application class or wherever you chose to initialise it.

Once you have a reference, it’s just a simple method call. Just add this piece of code in your onNewToken() method:

Kotlin
Java
token?.let {
mitter.registerFcmToken(
it,
object : Mitter.OnValueAvailableCallback<DeliveryEndpoint> {
override fun onValueAvailable(value: DeliveryEndpoint) {
//Delivery endpoint registered
}
override fun onError(error: ApiError) {
//Delivery endpoint failed to register, retry
}
}
)
}
if (token != null) {
mitter.registerFcmToken(
token,
new Mitter.OnValueAvailableCallback<DeliveryEndpoint>() {
@Override
public void onValueAvailable(DeliveryEndpoint deliveryEndpoint) {
//Delivery endpoint registered
}
@Override
public void onError(ApiError apiError) {
//Delivery endpoint failed to register, retry
}
}
);
}

Processing incoming FCM messages

Since FCM is a general purpose push messaging solution, you need to do a little setup for the SDK to actually make sense of the incoming messages.

There are just two simple steps involved:

  • Check whether the message is from Mitter.io

  • Pass the message to the SDK for processing

In a real-world production app, there’s a high chance that you’ll be using FCM for more than a single service. Therefore, it’s a wise choice to put a check to verify whether the incoming message should be processed by the Mitter SDK or by any other SDKs that you might use.

If the message is from Mitter.io, it needs to be forwarded to the SDK for processing.

The process is pretty simple. You just need to add this code in your onMessageReceived() method in your implementation of FirebaseMessagingService class:

Kotlin
Java
if (remoteMessage.data.isNotEmpty()) {
val messagingPipelinePayload = mitter.parseFcmMessage(remoteMessage.data)
if (mitter.isMitterMessage(messagingPipelinePayload)) {
mitter.processPushMessage(messagingPipelinePayload)
}
}
if (!remoteMessage.getData().isEmpty()) {
MessagingPipelinePayload messagingPipelinePayload = mitter.parseFcmMessage(remoteMessage.getData());
if (mitter.isMitterMessage(messagingPipelinePayload)) {
mitter.processPushMessage(messagingPipelinePayload, null);
}
}

Here, we’re initially checking if the message is non-empty by verifying the RemoteMessage object received from FCM.

After that is done, we proceed to parsing the message data and getting a MessagingPipelinePayload object in return. This object is in turn put to test by the isMitterMessage() method.

If it indeed is a valid message, we continue in processing this message by calling the processPushMessage() message and passing the previously obtained MessagingPipelinePayload object to it.

Now, the SDK will process all incoming messages and notify you of any relevant event. Speaking of getting notified, we need some mechanism to actually listen to any incoming events from the SDK.

This is exactly what you’ll be learning in the next section.

Listening to incoming events

All that you need to do to is to register some callbacks with the SDK and your app will always be notified of any relevant events.

To register a callback, you need to open up your Application class or wherever you’ve initialised the Mitter object. Then you need to register a callback on that object like this:

Kotlin
Java
mitter.registerOnPushMessageReceivedListener(object : Mitter.OnPushMessageReceivedCallback {
override fun onChannelStreamData(
channelId: String,
streamId: String,
streamData: ContextFreeMessage
) {
//Called when there's some streaming data such as typing indicator
}
override fun onNewChannel(channel: Channel) {
//Called when a new channel is created where the user is a participant
}
override fun onNewChannelTimelineEvent(
channelId: String,
timelineEvent: TimelineEvent
) {
//Called when there's a new timeline event for a channel
}
override fun onNewMessage(
channelId: String,
message: Message
) {
//Called when a new message has arrived for the user
}
override fun onNewMessageTimelineEvent(
messageId: String,
timelineEvent: TimelineEvent
) {
//Called when there's a new timeline event for a message
}
override fun onParticipationChangedEvent(
channelId: String,
participantId: String,
newStatus: ParticipationStatus,
oldStatus: ParticipationStatus?
) {
//Called when the user has joined a new channel or has been removed from one
}
})
mitter.registerOnPushMessageReceivedListener(new Mitter.OnPushMessageReceivedCallback() {
@Override
public void onNewMessage(
String channelId,
Message message
) {
//Called when a new message has arrived for the user
}
@Override
public void onNewChannel(Channel channel) {
//Called when a new channel is created where the user is a participant
}
@Override
public void onNewMessageTimelineEvent(
String messageId,
TimelineEvent timelineEvent
) {
//Called when there's a new timeline event for a message
}
@Override
public void onNewChannelTimelineEvent(
String channelId,
TimelineEvent timelineEvent
) {
//Called when there's a new timeline event for a channel
}
@Override
public void onParticipationChangedEvent(
String channelId, String participantId,
ParticipationStatus participationStatus,
ParticipationStatus participationStatus1
) {
//Called when the user has joined a new channel or has been removed from one
}
@Override
public void onChannelStreamData(
String channelId,
String streamId,
ContextFreeMessage contextFreeMessage
) {
//Called when there's some streaming data such as typing indicator
}
});

Just add your own callbacks or send out events from the Mitter callbacks to notify various parts of your app about any respective events that they need to handle.

Wrap up

Congratulations! Your app now works in real-time. In the next sections, you’ll be learning how to take full advantage of the SDK to spice up your app with presence updation, message read events and more.