Welcome to the reference section for Mitter’s Android SDK. In this section, you'll mostly find a detailed explanation of how the SDK works and how to harness it best.
What can you do with this SDK?
Mitter Android SDK gives you access to the entire Mitter.io platform from a User's perspective. The SDK does all the hard work behind the scenes while you focus on adding your business logic and getting your app ready in record time.
Currently, the Android SDK supports the following actions:
Sign-in as a user using either Google Sign-In or Auth Token
Create/remove channels
Send/receive messages & timeline events
Auto-updating your own presence and receiving other users’ presence
Updating your user profile
Setting up the SDK
All right, let’s get started by grabbing the SDK from jCenter.
Adding the SDK to your project
Adding the SDK to your project is pretty straightforward. Just open up your build.gradle file in the app module and paste this line within the dependencies block.
implementation 'io.mitter.android:core:0.1.7'
Once you’re done and just a Gradle sync and sit back while Gradle completes syncing your project.
Let’s do some basic configuration
Now that you’ve got the SDK added, the next step is to add some initial configuration for the SDK to work.
The central point of access to everything that the API has to offer is through the Mitter object. To start working, you need to configure this object with your application details that you can access from Mitter Dashboard.
A very good place to initialise and configure this object is within the onCreate() of your app’s Application class.
Let’s get started by defining the Mitter object as a global variable in your Application class.
lateinit var mitter: Mitter
private Mitter mitter;
Now, within onCreate() you need to configure this object to connect with your application on the Mitter.io platform. Additionally, you can put down some extra configuration as to how the SDK should behave locally.
The first thing we need is a UserAuth object which will specify the user you want the SDK to log in as. The UserAuth object takes a User ID and a User Auth Token as its parameters.
You need to get your user’s credentials from a backend server that connects to Mitter.io to manage your application. Alternatively, you can use a federated authentication system such as Google Sign-in to get the job done, which will be discussed in a later section. For brevity, let’s continue with the former approach:
UserAuth userAuth = new UserAuth(
"089771b6-6002-43db-bdc5-81e6ef7b6ef9",
"eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJtaXR0ZXItaW8iLCJ1c2VyVG9rZW5JZCI6Imc3QXYzYjR4VWJleGNsTTIiLCJ1c2VydG9rZW4iOiJyMHVsa2Jmc2ZtaWY5dTVscXNwaDVobzFpNCJ9.jnvR74f_GUBiH_9Z5FEWK7fLEnerDU_gCdPZeykKrJk5X4pOlhogVDG5PdeCyraz9FXV-G1sojlovpKuti7GTA"
);
Here, we configure the Mitter object with the User ID of 089771b6-6002-43db-bdc5-81e6ef7b6ef9 and its respective auth token which is nothing but a JWT.
Once that’s in place, you can do some application & local SDK configuration with the help of the MitterConfig object.
MitterConfig mitterConfig = new MitterConfig(
"ee421c5f-7a93-4b89-bf2a-4823c6e4fe42",
LoggingLevel.FULL,
null
);
Here, you just need to punch in your application ID which can be retrieved from the Mitter Dashboard. Additionally, if you want to configure how the SDK prints out logs you can do that by specifying one of either:
LoggingLevel.NONE - Prints nothing
LoggingLevel.BASIC - Prints only basic operation success/error messages
LoggingLevel.FULL - Prints out everything including object data. Not a good idea to use this level for production usage
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:
Before you start sending out messages, you need to create a channel with some participants in it. You’re free to define your channel however you want. Nevertheless, Mitter.io provides a list of default rulesets for channels that you can use to effortlessly create a channel.
What are channels?
Channels are nothing but containers for your messages. Think of it as a logical grouping for your messages. It defines who sees your messages that you send out in your application.
Creating a basic channel
Although the SDK has convenience methods for creating channels of all the kinds mentioned in the reference, for simplicity, we’ll focus on creating a one-to-one communication channel (also termed as a DirectChannel) here.
A channel needs participants to whom Mitter could deliver messages. Thankfully, creating participants is easy. Let’s define two participants for our channel:
val john = Participant("089771b6-6002-43db-bdc5-81e6ef7b6ef9")
val lucy = Participant("473d4f4f-0dc6-480b-ae94-7042b37f09e8")
Participant john = new Participant(
"089771b6-6002-43db-bdc5-81e6ef7b6ef9",
ParticipationStatus.Active
);
Participant lucy = new Participant(
"473d4f4f-0dc6-480b-ae94-7042b37f09e8",
ParticipationStatus.Active
);
Now that we have the participants in place, we can hook them up with a new DirectMessageChannel.
Once a channel has been created, you get a callback with the newly created channel’s identifier. You need to use this ID to send messages or get all messages on the channel.
Creating a channel with advanced properties
As already said, although the SDK provides you convenience methods to easily create a channel with a pre-defined ruleset, it doesn’t lock you down from customising your channel.
You can easily create a totally customised channel by using the Channel object and the createChannel() method.
Channel channel = new Channel(
"f8cc57d8-af38-4313-85e8-cbe62a2ebf23",
"",
"io.mitter.ruleset.chats.DirectMessage",
Arrays.asList(
new ChannelParticipation(
new User().setUserId("0b604184-7abd-453c-b258-7e4425b31e7f"),
ParticipationStatus.Active,
null,
null,
null
),
new ChannelParticipation(
new User().setUserId("ea4d2fe1-0d8d-42f0-afd3-8d8067ccbea1"),
ParticipationStatus.Active,
null,
null,
null
)
),
false,
new EntityMetadata(),
new EntityProfile(IdUtils.of(channelId, Channel.class), new ArrayList<Attribute>()),
new ArrayList<TimelineEvent>(),
new AppliedAclList(
new ArrayList<AppliedAcl>(),
new ArrayList<AppliedAcl>()
),
null
);
After you’ve constructed your Channel object, you can now swiftly create a new channel by calling the createChannel method:
It’s very similar to the createDirectMessageChannel() method, except you have full control over the channel parameters, including the channel ID.
When to use what?
Just remember this principle when creating channels with the SDK:
Quick and easy - Use createDirectMessageChannel() or createGroupMessageChannel()
Full customisation - Use createChannel()
Sending your first message
Nonetheless, you still get to create fully customised messages with custom payloads with the sendMessage() method.
What are messages?
Messages are the smallest unit of information in the Mitter.io platform. Don’t think of messages as just text or image messages, they’re more than that.
Sending your first message
Let’s say John wants to send a text message to Lucy on the channel that you just created. To achieve this, a simple method call with the channel ID and the message will suffice.
messaging.sendTextMessage(
channelId,
"Hi, Lucy!",
new AppliedAclList(
new ArrayList<AppliedAcl>(),
new ArrayList<AppliedAcl>()
),
new Mitter.OnValueUpdatedCallback() {
@Override
public void onSuccess() {
Toast.makeText(getApplicationContext(), "Yay! Message sent!", Toast.LENGTH_LONG).show();
}
@Override
public void onError(ApiError apiError) {}
}
);
That’s all you need to do get your plain text message delivered in a channel.
Fetching messages in a channel
Currently, the SDK provides two ways to receive messages in a channel:
The Pull approach - Calling getMessagesInChannel()
The Push approach - Listening to push messages through FCM
While the latter is more intuitive and probably the one you’ll end up using in most cases, for now, we’ll focus on the former and keep the Push approach for the next section.
Let’s say you want to fetch all the messages in a channel between John and Lucy. You can achieve that with the following piece of code:
messaging.getMessagesInChannel(
channelId = "f8cc57d8-af38-4313-85e8-cbe62a2ebf23",
onValueAvailableCallback = object : Mitter.OnValueAvailableCallback<List<Message>> {
override fun onValueAvailable(value: List<Message>) {
//We've got the messages
//Populate the messages in a list
}
override fun onError(apiError: ApiError) {}
}
)
messaging.getMessagesInChannel(
"f8cc57d8-af38-4313-85e8-cbe62a2ebf23",
new FetchMessageConfig(),
new Mitter.OnValueAvailableCallback<List<Message>>() {
@Override
public void onValueAvailable(List<Message> messageList) {
//We've got the messages
// Populate the messages in a list
}
@Override
public void onError(ApiError apiError) {}
}
);
By default, this call fetches the last 10 messages in the channel. You can raise this limit to a maximum of 50 messages by passing a FetchMessageConfig object to the method.
The code for the same would be:
val fetchMessageConfig = FetchMessageConfig(25)
messaging.getMessagesInChannel(
channelId = "f8cc57d8-af38-4313-85e8-cbe62a2ebf23",
fetchMessageConfig = fetchMessageConfig,
onValueAvailableCallback = object : Mitter.OnValueAvailableCallback<List<Message>> {
override fun onValueAvailable(value: List<Message>) {
//We've got the messages
//Populate the messages in a list
}
override fun onError(apiError: ApiError) {}
}
)
FetchMessageConfig fetchMessageConfig = new FetchMessageConfig(25, null, null);
messaging.getMessagesInChannel(
"f8cc57d8-af38-4313-85e8-cbe62a2ebf23",
fetchMessageConfig,
new Mitter.OnValueAvailableCallback<List<Message>>() {
@Override
public void onValueAvailable(List<Message> messageList) {
//We've got the messages
// Populate the messages in a list
}
@Override
public void onError(ApiError apiError) {}
}
);
When you need to cross the max limit of 25 you can opt for fetching messages in a paginated way, which will be discussed in a later section of this documentation.
Customising your message
As you’ve already done with your channel, you can also fully customise your messages. The SDK provides a sendMessage() method which accepts a Message object totally constructed by you.
Let’s see how it works. First, we need to create a TimelineEvent:
val sender = User().setUserId("0b604184-7abd-453c-b258-7e4425b31e7f")
val sentTimelineEvent = TimelineEvent(
type = StandardTimelineEventTypeNames.Messages.SentTime,
eventTimeMs = System.currentTimeMillis(),
subject = sender
)
Identifiable<User> sender = new User().setUserId("0b604184-7abd-453c-b258-7e4425b31e7f");
TimelineEvent sentTimelineEvent = new TimelineEvent(
UUID.randomUUID().toString(),
"",
StandardTimelineEventTypeNames.Messages.SentTime,
System.currentTimeMillis(),
sender,
null
);
Now that you have your TimelineEvent set, the only thing’s left is to create your customised Message object. Here’s how you can do that:
Message message = new Message(
"ad75460e-97c3-4785-9db7-20bcdaee93d9",
"",
StandardMessageType.Standard,
"com.acme.messages.MyCustomMessage",
sender,
"Check this out!",
Arrays.asList(
new MessageDatum(
"com.acme.data.MyCustomMessageData",
jacksonObjectMapper.valueToTree(messageData)
)
),
Arrays.asList(sentTimelineEvent),
new AppliedAclList(
new ArrayList<AppliedAcl>(),
new ArrayList<AppliedAcl>()
),
new EntityMetadata(),
null
);
The main part here is that you can supply a list of custom payloads in the messageData field. Use this field to define any custom buttons or additional styling information that you want to show up in the message.
All right, now that your Message object is set, it’s time that you send it. The sending part is really easy:
messaging.sendMessage(
channelId,
message,
new Mitter.OnValueUpdatedCallback() {
@Override
public void onSuccess() {
Toast.makeText(getApplicationContext(), "Yay! Message sent!", Toast.LENGTH_LONG).show();
}
@Override
public void onError(ApiError apiError) {}
}
);
And there you have it, your very own custom message with a custom payload.
Attaching images to your messages
Let’s see how you can create an ImageMessage with the SDK. It’s pretty similar to sending a text message, just with an added image file parameter:
messaging.sendImageMessage(
channelId = channelId,
caption = "The London Eye",
file = File("/storage/emulated/0/Download/london-eye.jpg"),
onValueUpdatedCallback = object : Mitter.OnValueUpdatedCallback {
override fun onSuccess() {
Log.d("Mitter", "Image message sent!")
}
override fun onError(error: ApiError) {
Log.d("Mitter", "Image Message Error: ${error.message}")
}
}
)
messaging.sendImageMessage(
channelId,
"The London Eye",
new File("/storage/emulated/0/Download/london-eye.jpg"),
new AppliedAclList(
new ArrayList<AppliedAcl>(),
new ArrayList<AppliedAcl>()
),
new Mitter.OnValueUpdatedCallback() {
@Override
public void onSuccess() {
Log.d("Mitter", "Image message sent!");
}
@Override
public void onError(ApiError apiError) {
Log.d("Mitter", "Image Message Error: " + apiError.getMessage());
}
}
);
Think of an ImageMessage as a regular image message that you see in every other messaging apps. You have an image with some text at the bottom, which is usually the caption.
You can do the same here. Just send a caption or whatever text you would prefer and a File object pointing to your image.
Wrap up
In this section, you’ve learnt how to use the Mitter Android SDK to create various types of channels as well as sending different messages into those channels.
Now, we’ll be focusing on how you can set up an FCM push message receiver to receive messages in real-time in your app.
You can learn more about in our reference section. For now, let’s just focus on creating some basic channels.
Like all other operations, sending messages is as easy as it gets. The SDK provides various methods of sending messages of which you can learn more about in the reference section.
You can translate almost any real-world action into an act of sending a particular type of message. You can learn more about in the reference section.
A TimelineEvent is like a categorised timestamp on your messages. Here, we’re specifying a SentTime event which is mandatory when creating a Message object. You can learn more about Timeline Events .
For more clarity, please refer to the detailed guide on messages over .
Mitter.io lets you create a pre-defined type of message called ImageMessage. The main advantage of choosing this type is that Mitter.io automatically generates thumbnails for the attached image without any effort from your part. For more details, .