Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Eclipse MQTT Android Client using single connection instance

I am using Eclipse Paho android mqtt service in my app. I am able to subscribe and publish the messages to mqtt broker. I have couple of Activities in the app, when any activity is started it connects to broker using mqttAndroidClient.connect(null, new IMqttActionListener() {} and gets the response in mqttAndroidClient.setCallback(new MqttCallback() {}.

My questions:

  1. Is this the correct way to implement the android mqtt service ?
  2. Is there a way to use same connection and callback instance throughout the app ?
like image 373
Pradip Shenolkar Avatar asked Dec 15 '22 02:12

Pradip Shenolkar


1 Answers

A 'better' way would be to create a Service which connects/reconnects to the MQTT Broker.

I created my own service called MqttConnectionManagerService which maintains and manages connection to the broker.

Key features of this solution:

  1. Service maintains a single instance as long as it is alive.
  2. If service is killed, Android restarts it (because START_STICKY)
  3. Service can be started when device boots.
  4. Service runs in the background and is always connected to receive notifications.
  5. If the service is alive, calling startService(..) again would trigger its onStartCommand() method (and not onCreate()). In this method, we simply check if this client is connected to the broker and connect/reconnect if required.

Sample code:

MqttConnectionManagerService

public class MqttConnectionManagerService extends Service {

    private MqttAndroidClient client;
    private MqttConnectOptions options;

    @Override
    public void onCreate() {
        super.onCreate();
        options = createMqttConnectOptions();
        client = createMqttAndroidClient();
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        this.connect(client, options);
        return START_STICKY;
    }

    private MqttConnectOptions createMqttConnectOptions() {
        //create and return options
    }

    private MqttAndroidClient createMqttAndroidClient() {
        //create and return client
    }

    public void connect(final MqttAndroidClient client, MqttConnectOptions options) {

        try {
            if (!client.isConnected()) {
                IMqttToken token = client.connect(options);
                //on successful connection, publish or subscribe as usual
                token.setActionCallback(new IMqttActionListener() {..});
                client.setCallback(new MqttCallback() {..});
            }
        } catch (MqttException e) {
            //handle e
        }
    }

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="...">

    <!-- Permissions required to receive BOOT_COMPLETED event -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- activities go here -->

        <!-- BroadcastReceiver that starts MqttConnectionManagerService on device boot -->
        <receiver android:name=".MqttServiceStartReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <!-- Services required for using MQTT -->
        <service android:name="org.eclipse.paho.android.service.MqttService" />
        <service android:name=".MqttConnectionManagerService" />
    </application>

</manifest>

MqttServiceStartReceiver

public class MqttServiceStartReceiver extends BroadcastReceiver {    
    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, MqttConnectionManagerService.class));
    }
}

In your Activity's onResume()

startService(new Intent(this, MqttConnectionManagerService.class));
like image 70
Pravin Sonawane Avatar answered Apr 07 '23 16:04

Pravin Sonawane