MQTT Paho Client无法自动重新连接到Android Service上的代理

MQTT Paho Client not reconnect automatically to broker on Android Service

我有一个服务来管理我的MQTT客户端连接,MQTT正常运行,但是问题是当我重新启动Broker Server时,Android客户端未重新连接。 onConnectionLost()回调触发异常。

笔记

  • 我在同一台计算机上使用Moquette Broker-> Moquette
  • 我有两个Android客户端应用程序,一个使用Service(有问题),另一个在不使用Service的线程上工作(这很好,重新连接就可以了)。
  • 我无法运行Android Client MQTT库,因为我正在使用Eclipse Paho MQTT。
  • 是的,我制作setAutomaticReconnect(true);
  • 问题

    使用Service的Android应用程序将永远运行,不会重新连接到MQTT Broker。

    MQTTService.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    public class MQTTService extends Service implements MqttCallbackExtended {

        boolean running;
    private static final String TAG ="MQTTService";

    public static final String ACTION_MQTT_CONNECTED ="ACTION_MQTT_CONNECTED";
    public static final String ACTION_MQTT_DISCONNECTED ="ACTION_MQTT_DISCONNECTED";
    public static final String ACTION_DATA_ARRIVED ="ACTION_DATA_ARRIVED";

    // MQTT
    MqttClient mqttClient;
    final String serverURI ="tcp://"+ServidorServices.IP+":1883";
    final String clientId ="Responsavel";
    String topicoId;
    Thread mqttStartThread;

    public boolean subscribe(String topic) {
        try {
            Log.i(TAG,"Subscripe:" + topic);
            mqttClient.subscribe(topic);
            mqttClient.subscribe("LOCATION_REAL");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    // Life Cycle
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG,"onBind()");
        return null;
    }

    @Override
    public void onCreate() {
        Log.d(TAG,"onCreate()");
        running = true;
        topicoId = getSharedPreferences("myprefs",MODE_PRIVATE).getString("tag_id_aluno","0");

        mqttStartThread = new MQTTStartThread(this);

        if(topicoId.equals("0")) {
            Log.i(TAG,"Error to subscribe");
            return;
        }

        mqttStartThread.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG,"onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    class MQTTStartThread extends Thread {

        MqttCallbackExtended mqttCallbackExtended;

        public MQTTStartThread(MqttCallbackExtended callbackExtended) {
            this.mqttCallbackExtended = callbackExtended;
        }

        @Override
        public void run() {
            try {
                mqttClient = new MqttClient(serverURI,clientId,new MemoryPersistence());
                MqttConnectOptions options = new MqttConnectOptions();
                options.setAutomaticReconnect(true);
                options.setCleanSession(true);
                mqttClient.setCallback(mqttCallbackExtended);
                mqttClient.connect();
            } catch (Exception e) {
                Log.i(TAG,"Exception MQTT CONNECT:" + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onDestroy() {
        Log.d(TAG,"onDestroy()");
        running = false;
        if (mqttClient != null) {
            try {
                if (mqttClient.isConnected()) mqttClient.disconnect();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG,"onUnbind()");
        return super.onUnbind(intent);
    }

    // Callbacks MQTT
    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
        Log.i(TAG,"connectComplete()");
        if (topicoId == null) {
            Log.i(TAG,"Erro ao ler ID da Tag");
            return;
        }
        sendBroadcast(new Intent(ACTION_MQTT_CONNECTED));
        subscribe(topicoId);
    }

    @Override
    public void connectionLost(Throwable cause) {
        Log.i(TAG,"connectionLost():" + cause.getMessage());
        cause.printStackTrace();
        sendBroadcast(new Intent(ACTION_MQTT_DISCONNECTED));
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        Log.i(TAG,"messageArrived() topic:" + topic);

        if (topic.equals("LOCATION_REAL")) {
            Log.i(TAG,"Data:" + new String(message.getPayload()));
        } else {
            Context context = MQTTService.this;
            String data = new String(message.getPayload());
            Intent intent = new Intent(context,MapsActivity.class);
            intent.putExtra("location",data);
            LatLng latLng = new LatLng(Double.valueOf(data.split("_")[0]),Double.valueOf(data.split("_")[1]));
            String lugar = Utils.getAddressFromLatLng(latLng,getApplicationContext());
            NotificationUtil.create(context,intent,"Embarque",lugar,1);

            if (data.split("_").length < 3) {
                return;
            }

            double latitude = Double.valueOf(data.split("_")[0]);
            double longitude = Double.valueOf(data.split("_")[1]);
            String horario = data.split("")[2];

            Intent iMqttBroadcast = new Intent(ACTION_DATA_ARRIVED);
            iMqttBroadcast.putExtra("topico",String.valueOf(topic));
            iMqttBroadcast.putExtra("latitude",latitude);
            iMqttBroadcast.putExtra("longitude",longitude);
            iMqttBroadcast.putExtra("evento","Embarcou");
            iMqttBroadcast.putExtra("horario",horario);

            sendBroadcast(iMqttBroadcast);
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        Log.i(TAG,"deliveryComplete()");
    }
    }

    Exception Stacktrace

    1
    2
    3
    4
    5
    6
    7
    8
    9
    I/MQTTService: connectionLost(): Connection lost
    W/System.err: Connection lost (32109) - java.io.EOFException
    W/System.err:     at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
    W/System.err:     at java.lang.Thread.run(Thread.java:818)
    W/System.err: Caused by: java.io.EOFException
    W/System.err:     at java.io.DataInputStream.readByte(DataInputStream.java:77)
    W/System.err:     at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
    W/System.err:     at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
    W/System.err:   ... 1 more


    我认为您忘记了在MqttClient对象中包含MqttConnectOptions

    请尝试以下

    mqttClient.connect(options);

    代替

    mqttClient.connect();

    希望它可以解决您的重新连接问题。


    如方法说明所述。

    1
      options.setAutomaticReconnect(true);

    客户端将尝试重新连接到服务器。 在尝试重新连接之前,它最初将等待1秒钟,对于每次失败的重新连接尝试,延迟将增加一倍,直到2分钟为止,此时延迟将保持2分钟。

    另一个选择是在连接丢失事件的情况下,您可以管理重试间隔。