> For the complete documentation index, see [llms.txt](https://docs.mitter.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mitter.io/sdks/android/real-time-communication.md).

# Set up FCM

### 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](https://docs.mitter.io/sdks/android/getting-started).

#### 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](https://firebase.google.com/docs/cloud-messaging/android/client) 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](https://cloud.google.com/resource-manager/docs/creating-managing-projects)
* 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](https://docs.mitter.io/platform-reference-1/delivery-endpoints) 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:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
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
            }
        }
    )
}
```

{% endtab %}

{% tab title="Java" %}

```java
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
            }
        }
    );
}
```

{% endtab %}
{% endtabs %}

#### 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:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
if (remoteMessage.data.isNotEmpty()) {
    val messagingPipelinePayload = mitter.parseFcmMessage(remoteMessage.data)

    if (mitter.isMitterMessage(messagingPipelinePayload)) {
        mitter.processPushMessage(messagingPipelinePayload)
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
if (!remoteMessage.getData().isEmpty()) {
    MessagingPipelinePayload messagingPipelinePayload = mitter.parseFcmMessage(remoteMessage.getData());
​
    if (mitter.isMitterMessage(messagingPipelinePayload)) {
        mitter.processPushMessage(messagingPipelinePayload, null);
    }
}
```

{% endtab %}
{% endtabs %}

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:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
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
    }
})
```

{% endtab %}

{% tab title="Java" %}

```java
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
    }
});
```

{% endtab %}
{% endtabs %}

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.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.mitter.io/sdks/android/real-time-communication.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
