# Setup

## Android

The Mitter.io Android SDK is distributed freely via **jCenter** and you can add it easily to your project by adding it as a standard dependency.

### Creating a new project

Create a new Android app project by following the standard procedure listed below. Alternatively, you can skip the setup part by cloning [**our starter template**](https://github.com/mitterio/mitter-android-starter) and loading it into Android Studio.

To create a project from scratch, do the following:

* Go to **File**
* Click on **New**, followed by **New Project**
* Follow the steps, keep everything set to default or customize to your needs

### Adding dependency

Now add the Android SDK to your newly created project by opening up your `build.gradle` file and pasting the following line in the **dependencies** block:

{% code title="build.gradle" %}

```groovy
implementation 'io.mitter.android:core:0.1.7'
```

{% endcode %}

Once that is added, perform a Gradle sync.

### Basic setup

Now that you’ve added the SDK, the next step is to add some initial configuration for the SDK to work.

> Note: This documentation contains code snippets for both Kotlin and Java. Switch to the relevant tab while building the demo.

To start working, you need to configure a `Mitter` object with your application details, which you can access from the Mitter.io Dashboard.

Before you proceed, visit the Mitter.io Dashboard, create an application and grab the application ID.

Next, you need to create a custom implementation of the `Application` class for your app. You can do so by creating a new class and extending the `Application` class:

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyApp.kt" %}

```kotlin
class MyApp: Application() {}
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyApp.java" %}

```java
class MyApp extends Application {}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Once that’s in place, override the `onCreate()` method. This is where you’ll be configuring the `Mitter` object.

Your custom `Application` class should look something like this:

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyApp.kt" %}

```kotlin
class MyApp: Application() {
    //Defining the mitter object
    lateinit var mitter: Mitter

    override fun onCreate() {
        super.onCreate()
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyApp.java" %}

```java
class MyApp extends Application {
    //Defining the mitter object
    private Mitter mitter;

    @Override
    public void onCreate() {
        super.onCreate();
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Just defining the `Mitter` object isn’t enough. You need to configure it with the application ID that you retrieved from the Mitter.io Dashboard.

Here's how to do that: Just paste this inside your `onCreate()` method in the `MyApp` class:

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyApp.kt" %}

```kotlin
val mitterConfig = MitterConfig(
    applicationId = "your-application-id-here"
)

mitter = Mitter(
    context = this,
    mitterConfig = mitterConfig
)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyApp.java" %}

```java
MitterConfig mitterConfig = new MitterConfig(
    "your-application-id-here",
    LoggingLevel.BASIC,
    null
);

mitter = new Mitter(
    this,
    mitterConfig,
    new UserAuth("", "")
);
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Using the SDK with containerised Mitter.io

If you're using the Mitter.io docker container, then you need to *override* the default API endpoint in the SDK, as follows:

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyApp.kt" %}

```kotlin
val mitterConfig = MitterConfig(
    applicationId = "your-application-id-here",
    apiEndpoint = MitterApiEndpoint(
        "http://localhost:11901",
        "http://localhost:11901"
    )
)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyApp.java" %}

```java
MitterConfig mitterConfig = new MitterConfig(
    "your-application-id-here",
    LoggingLevel.BASIC,
    new MitterApiEndpoint(
        "http://localhost:11901",
        "http://localhost:11901"
    )
);
```

{% endcode %}
{% endtab %}
{% endtabs %}

That’s all you need to do for the very basic configuration. It’s not ready to connect with the platform just yet, but we’ll get to that part in the later sections.

### Setup FCM

Mitter.io works hand-in-hand with **Firebase Cloud Messaging** (FCM) to deliver messages in real-time to Android devices.

To start receiving messages, you need to setup FCM in your Android app and make a couple of changes in your application in the Mitter.io Dashboard.

First of all, you need to setup FCM in your Android project. The steps for this setup are beyond the scope of this tutorial, and since Google has done a pretty good job explaining the same, you can [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 that's 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 the Mitter.io 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 this data, click on **New FCM Configuration Property**

Once you’ve completed these steps, you need to register a delivery endpoint for Mitter.io to deliver your messages.

In your Android project, create a class called `MyFirebaseMessagingService` which extends `FirebaseMessagingService` and override the `onNewToken()` method.

In the `onNewToken()` you need to get a reference to your `Mitter` object which you declared in your custom `Application` class.

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyFirebaseMessagingService.kt" %}

```kotlin
class MyFirebaseMessagingService: FirebaseMessagingService() {
    override fun onNewToken(token: String?) {
        val mitter = (application as MyApp).mitter
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyFirebaseMessagingService.java" %}

```java
public class MyFirebaseMessagingServiceJava extends FirebaseMessagingService {
    @Override
    public void onNewToken(String token) {
        Mitter mitter = ((MyApp) getApplication()).mitter;
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now that you have a reference to the `Mitter` object, you need to register the token with Mitter.io. Just add the following piece of code in your `onNewToken()` method:

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyFirebaseMessagingService.kt" %}

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

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyFirebaseMessagingService.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
            }
        }
    );
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Once that is done, the next step is to intercept any incoming push messages and pass them to the SDK for processing.

Get started by overriding the `onMessageReceived()` method and adding this piece of code inside the method:

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyFirebaseMessagingService.kt" %}

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

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

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyFirebaseMessagingService.java" %}

```java
if (!remoteMessage.getData().isEmpty()) {
    Mitter mitter = ((MyApp) getApplication()).mitter;
    MessagingPipelinePayload messagingPipelinePayload = mitter.parseFcmMessage(remoteMessage.getData());

    if (mitter.isMitterMessage(messagingPipelinePayload)) {
        mitter.processPushMessage(messagingPipelinePayload, null);
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Okay, the SDK is all set to intercept incoming messages and process them. The only thing that’s left is to register a callback on the `Mitter` object to get notified when a new message arrives.

Head back to your custom `Application` class and register a `OnPushMessageReceivedCallback` on the `Mitter` object that you had already created.

{% tabs %}
{% tab title="Kotlin" %}
{% code title="MyApp.kt" %}

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

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code title="MyApp.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
    }
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

You’re now done with the basic setup. Let’s move on to set up a user to start interacting with the platform and send messages.
