【Android】Android JavaでのMQTT接続方法と接続できなかった時の再接続方法

Java / Android

AndroidアプリでJavaを使用してMQTTに接続し、ネットワーク切断や接続失敗時に自動で再接続を行う実装方法をご紹介します

ここでは、定番の Eclipse Pahoライブラリ を使用します

1. Gradle依存関係の追加

build.gradle(Module: app)ファイルに、以下の依存関係を追加します

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}

※プロジェクトの設定によっては settings.gradle にリポジトリ(Eclipse PahoのMavenリポジトリなど)の追加が必要な場合があります。

2. AndroidManifest.xmlの設定

MQTT通信を行うために、インターネット接続の権限などを AndroidManifest.xml に追加します

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application ...>
    <!-- Eclipse Pahoのバックグラウンドサービス設定 -->
    <service android:name="org.eclipse.paho.android.service.MqttService" />
</application>

3. MQTT接続管理クラスの作成 (MqttHelper.java)

MQTTの接続、自動再接続、トピックのサブスクライブを管理するヘルパークラスを作成します

Java

import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.android.service.MqttAndroidClient;

import android.content.Context;
import android.util.Log;

public class MqttHelper {

    private MqttAndroidClient mqttAndroidClient;
    
    // ※テスト用のパブリックブローカーです。本番環境では自前サーバーやTLS接続をご利用ください。
    private final String serverUri = "tcp://broker.hivemq.com:1883";
    private final String clientId = MqttClient.generateClientId();
    private final String subscriptionTopic = "exampleTopic";
    private final String username = "yourUsername";
    private final String password = "yourPassword";

    public MqttHelper(Context context) {
        mqttAndroidClient = new MqttAndroidClient(context, serverUri, clientId);
        mqttAndroidClient.setCallback(new MqttCallbackExtended() {
            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                Log.d("MqttHelper", "Connected to: " + serverURI);
            }

            @Override
            public void connectionLost(Throwable cause) {
                Log.d("MqttHelper", "Connection lost, attempting to reconnect...");
                reconnect();
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                Log.d("MqttHelper", "Message received: " + new String(message.getPayload()));
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
            }
        });
        
        connect();
    }

    private void connect() {
        try {
            MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
            mqttConnectOptions.setAutomaticReconnect(true);
            mqttConnectOptions.setCleanSession(false);
            mqttConnectOptions.setUserName(username);
            mqttConnectOptions.setPassword(password.toCharArray());

            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d("MqttHelper", "Connected successfully.");
                    subscribeToTopic();
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.d("MqttHelper", "Failed to connect: " + exception.toString());
                    reconnect();
                }
            });
        } catch (MqttException ex) {
            ex.printStackTrace();
        }
    }

    private void subscribeToTopic() {
        try {
            mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d("MqttHelper", "Subscribed to topic: " + subscriptionTopic);
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.d("MqttHelper", "Failed to subscribe: " + exception.toString());
                }
            });
        } catch (MqttException ex) {
            ex.printStackTrace();
        }
    }

    private void reconnect() {
        try {
            mqttAndroidClient.connect(null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d("MqttHelper", "Reconnected successfully.");
                    subscribeToTopic();
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.d("MqttHelper", "Failed to reconnect: " + exception.toString());
                }
            });
        } catch (MqttException ex) {
            ex.printStackTrace();
        }
    }
}

4. MainActivityで使用する

最後に、MainActivity から MqttHelper を呼び出してMQTT接続を開始します

Java

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private MqttHelper mqttHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // MqttHelperの初期化と自動接続の開始
        mqttHelper = new MqttHelper(this);
    }
}

まとめ

このサンプルコードでは、AndroidアプリからMQTTブローカーへ接続し、通信が切断された場合に自動(または手動のコールバック経由)で再接続を試みる仕組みを実装しました

Eclipse Pahoライブラリを使用することで、バックグラウンドでの安定したMQTT操作が非常にシンプルに実現できます。ぜひお試しください!

コメント