In this tutorial we will show you how to integrate MQTT Chat android library version 1.2.0 in an android application from API 14.

DOWNLOAD CODE
VIDEO DEMO


Please note that we will use in server side the same database and the same web application of the mqttchat web tutorial. We are going to add other PHP files in rest folder which will serve as intermediary between android application and Mysql database.

mqtt chat app credentials

Let’s start creating our Android application.

1. Creating New Project

Create a new project in Android Studio from File ⇒ New Project by filling the required details.

As we need to make network requests, we need to add INTERNET permission in AndroidManifest.xml.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.test123">
    <application
        android:name=".mApplication"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".activity.SplashActivity">
           <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".activity.RegisterActivity" />
        <activity android:name=".activity.MainActivity" />
        <activity android:name=".activity.LoginActivity">
        </activity>
    </application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

Open app build.gradle and add MQTT Chat version 1.2.0 library dependencies. There are two sub-libraries: mqttchat-core which contains MQTT Chat core (business layer) and mqttchat-gui which contains the graphical interfaces (presentation layer).

You should also enable multidex support in android defaultConfig section like below:


android {
  defaultConfig {    
    multiDexEnabled true  
  }
}

dependencies {
    implementation 'com.telifoun.mqttchat:mqttchat-core:1.2.0'
    implementation 'com.telifoun.mqttchat:mqttchat-gui:1.2.0'
}     

To be able to access the MQTT Chat libraries, you must add MQTT Chat Artifactory repository to the list of Maven repositories in your project top level build.gradle file.


allprojects {
    repositories {       
        maven {
            url "https://mqttchat.jfrog.io/artifactory/libs-release-local"
            credentials {
                username = "mqttchat"
                password = "telifoun"
            }
        }
    }
}

2. MQTT Chat Initialisation

You should first get APP_ID and APP_SECRET from your MQTT Chat client area.

mqtt chat app credentials

In Application class mApplication.java add MQTT Chat initialisation code.


 public class mApplication extends MultiDexApplication {   
    @Override
    public void onCreate() {
        super.onCreate();
        new Mqttchat.getBuilder()
                .context(this.getApplicationContext())
                .appName(getApplicationContext().getResources().getString(R.string.app_name))
                .appIcon(R.mipmap.ic_launcher)
                .domain("test123.com")
                .appId("mqttchat-04939886")
                .appSecret("mqttchat-7izmgu617jiti6s0")
                .debugMode(true)
                .build();
    }
}

3. HTTP Client

Any android application that needs to store or to get data from a database must use web services. In this tutorial, to simplify we will use PHP pages which return JSON data. But be aware In a production application you must use secure REST services ...

There are several open source Android libraries that allow you to query web services. But since MQTT Chat already use VOLLEY library. We will use this library as HTTP client.


public class restRequest {
    public void request(int method, String url, HashMap<String,Object> data, final Callback clb){

        JsonObjectRequest newReq = new JsonObjectRequest(method,
                url, (data!=null)?new JSONObject(data):null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            if(response.getString("ok").equals("true")){
                             clb.OK(response);
                            }else{
                             clb.KO(response.getString("error"));
                            }
                        } catch (Exception ex) {
                            ex.printStackTrace();
                         clb.KO(ex.getMessage());
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {
                        try {
                            if (volleyError.networkResponse == null) {
                                clb.KO(volleyError.getMessage());
                            } else {
                               clb.KO(new JSONObject(new String(volleyError.networkResponse.data, "UTF-8")).getString("error"));
                            }
                        }catch (Exception ex) {
                            ex.printStackTrace();
                            clb.KO(ex.getMessage());
                        }

                    }
                });

        sdk.getInstance().addToRequestQueue(newReq);
    }

}

com.telifoun.mqttchat.core.Callback is a callback MQTT Chat abstract class that return OK on success and KO on error.


public abstract class Callback {
    public Callback() {}  
    public abstract void OK(Object var1);
    public abstract void KO(String var1);
}    

4. Add Application Config

Under app package, create a class named Config.java. This class contains app configuration information related to php files urls. Replace IP address below by your local webserver IP address.


public class Config {
    public static final String URL_REST_USER="http://192.168.1.10/mqtt_chat/rest/register.php";
    public static final String URL_REST_LOGIN="http://192.168.1.10/mqtt_chat/rest/login.php";
}    

5. Add new User

Add new empty activity RegisterActivity. Then Open the layout file for register activity (activity_register.xml).


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".RegisterActivity">

    <EditText
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="Name"
         />

    <EditText
        android:id="@+id/surname"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="SurName"
       />

    <EditText
        android:id="@+id/email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Email"
        android:inputType="textEmailAddress"
       />

    <EditText
        android:id="@+id/password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Password"
        android:inputType="textPassword"
         />

    <Spinner
        android:id="@+id/gender"
        android:padding="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawSelectorOnTop="true"
        android:entries="@array/gender_arrays"
       />

    <Button
        android:layout_marginTop="20dp"
        android:id="@+id/registerBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Register"
        />

</LinearLayout>

Now open the RegisterActivity.java and modify the code as below.

    
package com.test.test123.activity;

import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.telifoun.mqttchat.core.Callback;
import com.telifoun.mqttchat.gui.Mqttchat;
import com.telifoun.mqttchat.volley.toolbox.JsonObjectRequest;
import com.test.test123.Config;
import com.test.test123.R;
import com.test.test123.restRequest;
import org.json.JSONObject;
import java.util.HashMap;

public class RegisterActivity extends AppCompatActivity {

    private EditText name,surname,email,password;
    private Spinner gender;
    private Button registerButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        setTitle("Register");

        name=(EditText) findViewById(R.id.name);
        surname=(EditText) findViewById(R.id.surname);
        email=(EditText) findViewById(R.id.email);
        password=(EditText) findViewById(R.id.password);
        gender=(Spinner) findViewById(R.id.gender);

        registerButton=(Button) findViewById(R.id.registerBtn);
        registerButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                registerAction();
            }
        });
    }

    public void registerAction(){
        boolean cancel = false;
        View focusView = null;

        if (TextUtils.isEmpty(name.getText().toString()) ||
                (name.getText().length()<2)) {
            name.setError(getString(R.string.error_field_required));
            cancel=true;
            focusView=name;
        }
        if (TextUtils.isEmpty(surname.getText().toString()) ||
                (surname.getText().length()<2)) {
            surname.setError(getString(R.string.error_field_required));
            cancel=true;
            focusView=surname;
        }
        if (TextUtils.isEmpty(email.getText().toString())) {
            email.setError(getString(R.string.error_field_required));
            cancel=true;
            focusView=email;
        }
        if (TextUtils.isEmpty(password.getText().toString())) {
            password.setError(getString(R.string.error_field_required));
            cancel=true;
            focusView=password;
        }

        if(cancel){
            focusView.requestFocus();
        }else{
            restRegister();
        }
    }

    private void restRegister(){
        final ProgressDialog mProgressDialog = ProgressDialog.show(this, "register",
               "registring new user", true);

        HashMap user_data=new HashMap();
        user_data.put("name", name.getText().toString());
        user_data.put("surname",surname.getText().toString());
        user_data.put("email", email.getText().toString());
        user_data.put("password",password.getText().toString());
        user_data.put("gender",gender.getSelectedItemPosition());

        (new restRequest()).request(JsonObjectRequest.Method.POST, Config.URL_REST_USER, user_data, new Callback() {
            @Override
            public void OK(Object o) { // register success

                try {
                    JSONObject userJson = ((JSONObject) o).getJSONObject("response");
                    final int userId= userJson.getInt("id");

                        Mqttchat.getmInstance().logIn(getApplicationContext(),userId, new Callback(){
                                @Override
                                public void OK(Object o) {
                                    mProgressDialog.dismiss();                                    
                                    Intent myIntent = new Intent(RegisterActivity.this, MainActivity.class);
                                    startActivity(myIntent);
                                    finish();
                                }
                                @Override
                                public void KO(String s) {
                                    mProgressDialog.dismiss();
                                    Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
                                }
                        });
                }catch(Exception ex){
                    mProgressDialog.dismiss();
                    Toast.makeText(getApplicationContext(),ex.getMessage(),Toast.LENGTH_SHORT).show();
                }

            }

            @Override
            public void KO(String s) { //register fail
                mProgressDialog.dismiss();
                Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
            }
        });
    }
}
mqtt chat app register

As you can see in the register.java activity we have:

1. Saved the new user in the Mysql database using the HTTP Client seen in section 3. In server side we used the file register.php below.

2. When new user is successfully saved in database, he is then added to MQTT Chat using PHP SDK Add function.


<?php
   include("../include/db_connect.php");    

   // Turn autocommit off
   $dbh -> autocommit(FALSE);
   
   if ( !isset( $HTTP_RAW_POST_DATA ) ) $HTTP_RAW_POST_DATA =file_get_contents( 'php://input' );
   $data=json_decode($HTTP_RAW_POST_DATA,true);   

   $name = mysqli_real_escape_string($dbh,$data['name']);
   $surname = mysqli_real_escape_string($dbh,$data['surname']);
   $mail = mysqli_real_escape_string($dbh,$data['email']);
   $password = mysqli_real_escape_string($dbh,$data['password']); 
   $gender= mysqli_real_escape_string($dbh,$data['gender']);
      
   $sql = "INSERT INTO users (id, name, surname,mail,password,gender)
           VALUES (null,'$name', '$surname', '$mail' ,'$password',$gender)";
   
   if (mysqli_query($dbh,$sql) === TRUE) {   
       
       require_once  dirname(__FILE__) .DIRECTORY_SEPARATOR."vendor/autoload.php";
       
       $userId=$dbh->insert_id;
       
       $users=new telifoun\mqttchat\users();
       $post_array=array("userid"=>$userId,
                         "name"=>$name,
                         "surname"=>$surname,
                         "profile_link"=>"",
                         "avatar_link"=>"",
                         "gender"=>$gender);
       
        $response=$users->add($post_array);         
        if($response["ok"]){
           // Commit transaction 
           $dbh -> commit();           
           $result=array("ok"=>true,"response"=>array("id"=>$userId));            
        }else{  
           // Rollback transaction
           $dbh -> rollback();  
           $result=array("ok"=>false,"error"=>$dbh->$response["error"]);   
        }
        
   } else {
        $result=array("ok"=>false,"error"=>$dbh->error);
   }
   
  $dbh-> close();
    
  header('Content-type: application/json; charset=utf-8');
  echo json_encode($result);
  exit;

3. Finally user is logged to chat using MQTT Chat logIn function and can start chating.

6. User Login

LoginActivity is used to authenticate a registred user. So add new empty activity LoginActivity and open layout file for login activity (activity_login.xml).


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LoginActivity">

    <EditText
        android:id="@+id/email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Email"
        android:inputType="textEmailAddress"
        />

    <EditText
        android:id="@+id/password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Password"
        android:inputType="textPassword"
        />


    <Button
        android:layout_marginTop="20dp"
        android:id="@+id/loginBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login"
        />


    <Button
        android:layout_marginTop="20dp"
        android:id="@+id/registerBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Register"
        />

</LinearLayout>

Now open LoginActivity.java and modify the code as below.

 
package com.test.test123.activity;

import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.telifoun.mqttchat.core.Callback;
import com.telifoun.mqttchat.gui.Mqttchat;
import com.telifoun.mqttchat.volley.toolbox.JsonObjectRequest;
import com.test.test123.Config;
import com.test.test123.R;
import com.test.test123.restRequest;

import org.json.JSONObject;
import java.util.HashMap;

public class LoginActivity extends AppCompatActivity {
    private EditText mail;
    private EditText password;
    private Button registerBtn;
    private Button loginBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_login);
        mail=(EditText) findViewById(R.id.email);
        password=(EditText) findViewById(R.id.password);
        Button loginBtn=(Button) findViewById(R.id.loginBtn);
        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkLogIn();
            }
        });
        Button registerBtn=(Button) findViewById(R.id.registerBtn);
        registerBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                Intent myIntent = new Intent(LoginActivity.this, RegisterActivity.class);
                startActivity(myIntent);
            }
        });
    }

    private void checkLogIn(){
        boolean cancel = false;
        View focusView = null;

        if (TextUtils.isEmpty(mail.getText().toString()) ||
                (mail.getText().length()<5)) {
            mail.setError(getString(R.string.error_field_email));
            cancel=true;
            focusView=mail;
        }
        if (TextUtils.isEmpty(password.getText().toString()) ||
                (password.getText().length()<4)) {
            password.setError(getString(R.string.error_field_password));
            cancel=true;
            focusView=password;
        }
        if(cancel){
            focusView.requestFocus();
        }else{
            logIn();
        }
    }

    private void logIn(){
        final ProgressDialog mProgressDialog = ProgressDialog.show(this, "User Login",
               "Login user to APP", true);
        HashMap user_data=new HashMap();
        user_data.put("mail", mail.getText().toString());
        user_data.put("password",password.getText().toString());

        (new restRequest()).request(JsonObjectRequest.Method.POST, Config.URL_REST_LOGIN, user_data, new Callback(){
            @Override
            public void OK(Object o) {
                try {
                    /** Get user Id **/
                    JSONObject userJson = ((JSONObject) o).getJSONObject("response");
                    final int userId= userJson.getInt("id");
                    /** Login to MQTTCHAT **/
                    Mqttchat.getmInstance().logIn(getApplicationContext(),userId, new Callback(){
                        @Override
                        public void OK(Object o) {
                            mProgressDialog.dismiss();
                            finish();
                            Intent myIntent = new Intent(LoginActivity.this, MainActivity.class);
                            startActivity(myIntent);

                        }
                        @Override
                        public void KO(String s) {
                            mProgressDialog.dismiss();
                            Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
                        }
                    });

                }catch (Exception e){
                    mProgressDialog.dismiss();
                    Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void KO(String s) {
                mProgressDialog.dismiss();
                Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
            }
        });
    }
}

mqtt chat app register

As you can see in LoginActivity.java activity we have:

1. Used the HTTP Client seen in section 3 to check user login and password. In server side we used the file login.php that return user Id in case authentication success.


<?php
   include("../include/db_connect.php");  
   
   if ( !isset( $HTTP_RAW_POST_DATA ) ) $HTTP_RAW_POST_DATA =file_get_contents( 'php://input' );
   $data=json_decode($HTTP_RAW_POST_DATA,true);   

    $mail = mysqli_real_escape_string($dbh,$data['mail']);
    $password = mysqli_real_escape_string($dbh,$data['password']); 
      
    $sql = "SELECT id FROM users WHERE mail = '$mail' and password = '$password'";
    $result = mysqli_query($dbh,$sql);
    $row = mysqli_fetch_array($result,MYSQLI_ASSOC);      
     
      // If result matched $myusername and $mypassword, table row must be 1 row
      if($row["id"]>0) {        
       $result=array("ok"=>true,"response"=>array("id"=>$row["id"]));
      }else {
       $result=array("ok"=>false);
      }
    
  header('Content-type: application/json; charset=utf-8');
  echo json_encode($result);
  exit;

2. When remote authentication succeeded, the user is then logged to MQTT Chat using MQTT Chat logIn function and can start chating.

7. Use of Splash Activity

To prevent user from logging in each time the application is launched. You can use a sharedprefrences file to save user id when authentication succeeded. You can then use the SplashActivity to check if user id is already saved on it. If yes then you can redirect him to the chat interface directly otherwise it is redirected to LoginActivity.

SplashActivity should be configured as louncher activity of the application in the AndroidManifest.xml file. The java code that can be used looks like the code below:


package com.test.test123.activity;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import com.telifoun.mqttchat.gui.Mqttchat;
import com.test.test123.R;

public class SplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        check_login();
    }

    private void check_login(){
        Intent myIntent;
        if(Mqttchat.getmInstance().getLoggedUser().isLogged()){
           myIntent = new Intent(SplashActivity.this, MainActivity.class);
        }else{
           myIntent = new Intent(SplashActivity.this, LoginActivity.class);
        }
        startActivity(myIntent);
        finish();
    }
}

8. Show Chat GUI

First open the layout file for main activity (activity_main.xml) and add the following XML code.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/logoutBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Log Out"
      />

    <FrameLayout
        android:name="com.telifoun.mqttchat.gui.MqttchatFragment"
        android:id="@+id/mqttchatFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout> 

Use the code below in MainActivity.java to show MQTT Chat Fragment.

There are two important things to note:

  • 1. We added a log out button to allow user to disconnect from MQTT Chat. The click event include call to the MQTT Chat logOut function.
  • 2. MainActivity extends presenceactivityA. This is important to keep presence system running see documentation.

package com.test.test123.activity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.telifoun.mqttchat.core.Callback;
import com.telifoun.mqttchat.core.presence.PresenceActivityA;
import com.telifoun.mqttchat.gui.Mqttchat;
import com.telifoun.mqttchat.gui.MqttchatFragment;
import com.test.test123.R;

public class MainActivity extends PresenceActivityA {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button logOutBtn=(Button) findViewById(R.id.logoutBtn);
        logOutBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Mqttchat.getmInstance().logOut(new Callback() {
                    @Override
                    public void OK(Object o) {
                        Intent myIntent = new Intent(MainActivity.this, LoginActivity.class);
                        startActivity(myIntent);
                        finish();
                    }

                    @Override
                    public void KO(String s) {
                        Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });

        if(savedInstanceState==null) {
           getSupportFragmentManager().beginTransaction().add(R.id.mqttchatFragment, MqttchatFragment.newInstance(), "mqttchat").commit();
        }
    }
}
mqtt chat app android
mqtt chat app web

You can try audio and video calls between Web and Android applications.

mqtt chat app android 3
mqtt chat app web 3

9. Offline Calls and Notifications

MQTT Chat uses FCM (Firebase Cloud Messaging) to send notifications when new messages are received and to route audio and video calls when the application is closed.

FCM functionality is not activated by default, to activate it for your application, you must follow all steps indicated in the FCM section of the Android documentation

Don't forget to add FCM Server key to your MQTT Chat FCM settings in your client Area.

mqtt chat app android 3

If all config is ok you will automatically receive notifications and calls even if your android application is closed.

mqtt chat app android 4
mqtt chat app web 4

10. Custom colors

You can customize Mqttchat GUI colors to match your android application theme. For more information please read custom colors android documentation section.

In this tutorial we will change our MQTT Chat GUI colors by editing color.xml ressource file as below


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#3D99D7</color>
    <color name="colorWhite">#FFFFFF</color>
    <color name="mqttchat_colorPrimary">#FFF</color>
    <color name="mqttchat_textColorPrimary">#1B71A5</color>
</resources>

GUI Result is as below:

mqtt chat app android 5

That's it for this tutorial. I hope that through a practical example MQTT Chat android library integration is clearer.

Do not forget to minimize the size of your android application before publishing it to Google Play. Please read Decreasing Application size documentation section. If you are facing any issue in this tutorial, please comment in below discussions.