Moxtra Chat SDK for Android

Use the Moxtra Chat SDK module to add rich collaboration to your app.

What features you will get with the SDK:

  • Ability to do one-on-one and/or group chats
  • Share files
  • Layer visual & voice annotations on top of files
  • Conduct real-time meetings

Let's get started by using a sample app "Moxie Chat". In this tutorial, you will learn how to integrate the Moxtra Chat SDK in your app.

The diagram below explains how the sample app "Moxie Chat" will interact with Moxtra.

App Architecture

Setup

Asynchronous programming

You should have some basic knowledge of asynchronous programming. This type of programming involves calling an API with a XXXListener parameter and then waiting for the listener callback before continuing with next steps.

Register

Before proceeding further, ensure you have registered your app with Moxtra.

Clone the sample project from github

Please clone the sample project MoxieChat from here:

git clone https://github.com/Moxtra/moxtra-chat-android-sample MoxieChat

  • If you don't have git installed, you can download and install git from http://git-scm.com.

Step 0: Create an empty project in Android Studio

This tutorial uses Android Studio to create the sample app 'Moxie Chat'. Ensure you have installed Android Studio and the Android SDK (launch the SDK Manager in Android Studio and follow the setup wizard to install) before proceeding further.

You can start by creating an empty project using Android Studio.

Step 1: Add the Moxtra Chat SDK dependency

After creating the MoxieChat empty project, it's time to add the Moxtra Chat SDK dependency to it.

First, we need to add the Moxtra Maven Repo URL to let gradle know where do download the dependencies.

Edit the build.gradle under the MoxieChat and add the following code snippet:

maven() {
    url "http://maven.moxtra.com:8081/nexus/content/groups/public"
}

And add the following dependency to the build.gradle file in the app folder:

compile "com.moxtra:chat-sdk:${CHAT_SDK_VERSION}"

You can now sync the project with gradle files:

Tools -> Android -> Sync Project with Gradle Files

Make sure you do not have any compile errors before proceeding further.

Step 2: Build scaffold and adding test data

In this step you will build the scaffold for your app and add some user data for testing.

The Moxtra Chat SDK has NO user management feature and it's up to you to define it. In this tutorial, you can use some test data.

Step 3: Implement the login and logout functionality

This tutorial covers only the login/setup user flow related to Moxtra Chat SDK shown below.

The login flow looks like this:

Login Flow

You should initialize ChatClient when starting your app. For the purpose of this tutorial, you can initialize it in the Application as shown in the code snippet below:

@Override
public void onCreate() {
    super.onCreate();
    ChatClient.initialize(this);
}

The linkXXX is an asynchronous operation and requires to pass a callback to it. The callback interface can be implemented as shown below:

ChatClient.linkWithUniqueID(uniqueId, clientId, clientSecret, orgId, baseDomain,
    new ApiCallback() {
        @Override
        public void onCompleted(ChatClientDelegate ccd) {
            Log.i(TAG, "Linked to Moxtra account successfully.");
            PreferenceUtil.saveUser(mContext, uniqueId);
            startChatListActivity();
        }
        
        @Override
        public void onError(int errorCode, String errorMsg) {
            Log.e(TAG, "Failed to link to Moxtra account, errorCode=" +
            errorCode + ", errorMsg=" + errorMsg);
            showProgress(false);
        }
});

We pass clientId and clientSecret (2nd and 3rd parameters, you should replace it with your clientId and clientSecret when building your app). And set the baseDomain to development environment (sandbox.moxtra.com). When you are ready to move into production (www.moxtra.com), contact us.

The clientSecret should be confidential and you'd better to store it on your server side. It has two advantages:

  • Relatively secure and hard to hack in.
  • You can change the secret later and it will not impact your current distributted app client.

After the user has successfully logged out from your app, unlink the Moxtra account. In MoxieChat (or in this tutorial, it is implemented in the BaseActivity Action Toolbar so the user can logout from any activity that extends BaseActivity).

ChatClient.unlink(new ApiCallback() {
    @Override
    public void onCompleted(Void result) {
        Log.i(TAG, "Unlink Moxtra account successfully.");
    }

    @Override
    public void onError(int errorCode, String errorMsg) {
        Log.e(TAG, "Failed to unlink Moxtra account, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
    }
});

Step 4: Show the chat list

Two scenarios need to be considered when showing the chat list:

  • Initializing the chat list when a user opens your app
  • Updating the user of any updates to the chats when the user is inside the chat list UI of your app.

Now let's build the chat list using the ChatRepo API. To get an instance of the ChatRepo, you can use the following code snippet:

mChatRepo = mChatClientDelegate.createChatRepo();

When a user opens the chat list UI, you can call the following API to get all the chats:

List chatList = mChatRepo.getList();

After getting a list of all chat sessions, you have to listen for changes so the UI can be updated automatically.

mChatRepo.setOnChangedListener(new BaseRepo.OnRepoChangedListener() {
    @Override
    public void onCreated(List items) {
        mAdapter.updateChats(mChatRepo.getList());
    }

    @Override
    public void onUpdated(List items) {
        mAdapter.updateChats(mChatRepo.getList());
    }

    @Override
    public void onDeleted(List items) {
        mAdapter.updateChats(mChatRepo.getList());
    }
});

Step 5: Start a new chat

In the sample app, you now have an empty chat list.

You have to build the UI to select another user to chat by calling the following API:

mChatRepo.createGroupChat(topic, new ApiCallback() {
    @Override
    public void onCompleted(Chat chat) {
        Log.i(TAG, "Create group chat successfully.");
        mChat = chat;
        mChat.inviteMembers(orgId, uniqueIdList, new ApiCallback() {
            @Override
            public void onCompleted(Void result) {
                Log.i(TAG, "Invite members successfully.");
            }

            @Override
            public void onError(int errorCode, String errorMsg) {
                Log.e(TAG, "Failed to invite members, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
            }
        });
        showChatFragment();
    }

    @Override
    public void onError(int errorCode, String errorMsg) {
        Log.e(TAG, "Failed to create group chat, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
        finishInMainThread();
    }
});

As you may have noticed from the last parameter in the API call, the apiCallback is an asynchronous operation.

In the Moxtra Chat SDK, all operations with a XXXCallback are asynchronous operations. The result of this asynchronous operation is not known until a callback is fired.

Step 6: Open an existing chat

To open an existing chat from the chat list UI by calling the following API:

mChatController = mChatClientDelegate.createChatController(mChat);
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.chat_frame);
if (fragment == null) {
    fragment = mChatController.createChatFragment();
    getSupportFragmentManager().beginTransaction().add(R.id.chat_frame,
    fragment).commit();
}

Step 7: Start a meet

With Moxtra Chat SDK, you can easily start an audio/video meeting with a few lines of code. You can aslo share your screen and annotate documents inside the meeting.

This step is required only if you implement the start meet functionality outside the chat UI.

To start a meeting outside the Chat UI, use the following code snippet:

mMeetRepo = mChatClientDelegate.createMeetRepo();
mMeetRepo.startMeetWithTopic(topic, new ApiCallback() {
    @Override
    public void onCompleted(MeetSession meetSession) {
        Log.i(TAG, "Start meet successfully.");
        mMeetSession = meetSession;
        mMeetSession.inviteParticipants(userList, new ApiCallback() {
            @Override
            public void onCompleted(Void result) {
                Log.i(TAG, "Invite participants successfully.");
            }

            @Override
            public void onError(int errorCode, String errorMsg) {
                Log.i(TAG, "Failed to invite participants, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
            }
        });
        mMeetSessionController = mChatClientDelegate.createMeetSessionController(mMeetSession);
        showMeetFragment();
    }

    @Override
    public void onError(int errorCode, String errorMsg) {
        Log.e(TAG, "Failed to start meet, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
        finishInMainThread();
    }
});

Please implement the callback interface to determine if the meeting was started successfully.

After that, you are able to show meet fragment in your activity,

Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.meet_frame);
if (fragment == null) {
    fragment = mMeetSessionController.createMeetFragment();
    getSupportFragmentManager().beginTransaction().add(R.id.meet_frame,
    fragment).commit();
}

Step 8: Join a meet

Invited users should be able to join a meeting. Use this code snippet to implement the join meeting functionality.

mMeetRepo.joinMeet(meet.getID(), new ApiCallback() {
    @Override
    public void onCompleted(MeetSession meetSession) {
        Log.i(TAG, "Join meet successfully.");
        mMeetSession = meetSession;
        mMeetSessionController = mChatClientDelegate.createMeetSessionController(mMeetSession);
        showMeetFragment();
    }

    @Override
    public void onError(int errorCode, String errorMsg) {
        Log.e(TAG, "Failed to join meet, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
        finishInMainThread();
    }
});

Step 9: Delete Chat

Every chat that is created is a persistent chat. Chat messages are saved over time, so new and old chat members can see all the chat history at any time.

If you have a chat that is no longer required, then it can be deleted. Use this code snippet to implement the Delete Chat functionality.

mChatRepo.deleteOrLeaveChat(chat, new ApiCallback() {
    @Override
    public void onCompleted(Void result) {
        Log.i(TAG, "Leave or delete chat successfully.");
    }

    @Override
    public void onError(int errorCode, String errorMsg) {
        Log.e(TAG, "Failed to leave or delete chat, errorCode=" + errorCode + ", errorMsg=" + errorMsg);
    }
});

Step 10: Enable notifications

Notification is an essential feature for a real-time communication app. For this example you will use GCM (Google Cloud Messaging) based solution for notifications. You can also use long-connection if for some reason GCM cannot be used, for details on using long-connection please click here.

Get API Key from Google Developer Console:

  • Go to https://console.developers.google.com/project
  • Click on Create Project or use an existing project
  • Go to the project overview page and note down the Project Number.
  • Click APIs under APIs & auth section and then click Cloud Messaging for Android to make sure the API is enabled. If not, please enable now.
  • Click Credentials under APIs & auth section and get the API Key. If you don't have any API Key, please click Create new Key and select Server key to create.

Now, you need to set the API key in the Moxtra developer console so that the GCM server will not refuse the notification.

  • Go to My Apps
  • Find your app and click Edit application
  • Scroll to the bottom of the page and you will find the section "For Android devices".
  • Set the API Key and click Update to save the key to your app configuration.

Next, you need to write code to register the device when a user logs in successfully. Please check Integrate Google Cloud Messaging for more details. Note that the project number is the GCM sender ID.

On successful user login and registration of the device, get the register id (regId) from the GCM server. Use the regId in the Setup User call as shown in the code snippet below:

chatClientDelegate.getNotificationManager().setNotificationDeviceToken(regId);

The Moxtra server can now send notification to the device if registered. In order to show the notifications, please refer to Integrate Google Cloud Messaging. In this tutorial the Moxtra related code is highlighted the Moxtra related part here.

After getting a notification, call isValidRemoteNotification to preprocess it and check if it is a Moxtra message.

NotificationManager notificationManager = ChatClient.getClientDelegate().getNotificationManager();
if (notificationManager.isValidRemoteNotification(intent)) {
    int type = notificationManager.getValidNotificationType(intent);
    String title = notificationManager.getNotificationMessageText(this, intent);
    Log.i(TAG, "Here comes a notification: type=" + type + ", title=" + title);
    sendNotification(title, null, intent);
} else {
    Log.w(TAG, "Ignore invalid remote notification.");
}

If it is a moxtra message, process and send the notification as shown in the code snippet below:

private void sendNotification(String msg, Uri uri, Intent intent) {
    Intent notificationIntent = new Intent(this, ChatListActivity.class);
    if (intent != null) {
        notificationIntent.putExtras(intent);
    }
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(getString(getApplicationInfo().labelRes))
            .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
            .setContentText(msg)
            .setAutoCancel(true)
            .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE);
    if (uri != null) {
        mBuilder.setSound(uri);
    }
    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}

Step 11: Prepare for release

In order to prepare your app for release, you should set up the signing configuration. Don't forget to update the proguard rules.

API Reference

This tutorial covers only a few APIs. For a full list of APIs, please refer to our Android Chat SDK: API Reference Guide.

Current Version - V 4.0.6 (October 2nd 2017)