2016-08-02 1 views
1

J'essaie d'utiliser la version de base du client MQTT Eclipse Paho MQTT version 1.1.0 pour me connecter à une instance RabbitMQ de CloudAMQP, m'abonner à un sujet et recevoir des messages (que j'envoie sur le Web console d'administration).Paho Le client Android interrompt la connexion lorsqu'un message est affiché

Cela fonctionne bien si l'application envoie toutes les charges utiles de message à la sortie du journal.

Si l'application ajoute le message à une TextView, le message s'affiche, mais la connexion est immédiatement supprimée et aucun autre message n'est reçu.

Le projet complet est disponible au GitHub. Un exemple simple est ci-dessous. Il y a un client Paho MQTT basé sur le service, mais je pensais que pour les applications très simples, le client de base devrait pouvoir recevoir et afficher des messages dans l'interface utilisateur de l'application Android.

... 

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; 
import org.eclipse.paho.client.mqttv3.MqttCallback; 
import org.eclipse.paho.client.mqttv3.MqttClient; 
import org.eclipse.paho.client.mqttv3.MqttClientPersistence; 
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.client.mqttv3.persist.MemoryPersistence; 

public class MainActivity extends AppCompatActivity implements MqttCallback { 

    private static final String TAG = "main"; 
    private Connection connection; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     configureUI(); 
    } 

    private Button buttonConnect; 
    private TextView messageWindow; 


    private void configureUI() { 
     buttonConnect = (Button) findViewById(R.id.buttonConnect); 
     messageWindow = (TextView) findViewById(R.id.messageWindow); 

     buttonConnect.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       String s = "***"; 
       String d = "test"; 
       String u = "***"; 
       String p = "***"; 

       if (connection != null && connection.isConnected()) { 
        connection.disconnect(); 
        connection = null; 
        messageWindow.setText(String.format("Disconnected from server %s", 
          new Object[]{s})); 
        return; 
       } 

       messageWindow.setText(String.format("Connecting to server %s as user %s", 
         new Object[]{s, u})); 

       connection = new Connection(MainActivity.this, MainActivity.this, s, u, p); 
       connection.connect(); 

       if (connection.isConnected()) { 
        messageWindow.append("\n\n"); 
        messageWindow.append(String.format("Connected, listening for messages from topic %s", 
          new Object[]{d})); 
        connection.subscribe(d); 
       } 
      } 
     }); 
    } 

    @Override 
    public void connectionLost(Throwable cause) { 
     Log.e(TAG, "connectionLost" + cause.getMessage()); 
    } 

    @Override 
    public void messageArrived(String topic, MqttMessage message) throws Exception { 
     String msg = new String(message.getPayload()); 
     Log.i(TAG, "Message Arrived: " + msg); 
     // messageWindow.append(msg); 
    } 

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

    class Connection { 
     private static final String TAG = "conn"; 
     private static final String protocol = "tcp://"; 
     private static final int port = 1883; 
     private static final int version = MqttConnectOptions.MQTT_VERSION_3_1_1; 
     private static final int keepAliveSeconds = 20 * 60; 

     private final Context context; 
     private MqttClient client; 

     private final String server; 
     private final String user; 
     private final String pass; 

     private final MqttConnectOptions options = new MqttConnectOptions(); 

     public Connection(Context ctx, MqttCallback mqttCallback, String server, String user, String pass) { 
      this.context = ctx; 
      this.server = server; 
      this.user = user; 
      this.pass = pass; 

      MqttClientPersistence memPer = new MemoryPersistence(); 
      try { 
       String url = protocol + server + ":" + port; 
       client = new MqttClient(url, MqttClient.generateClientId(), memPer); 
       client.setCallback(mqttCallback); 
      } catch (MqttException e) { 
       e.printStackTrace(); 
      } 

      options.setUserName(user + ":" + user); 
      options.setPassword(pass.toCharArray()); 
      options.setMqttVersion(version); 
      options.setKeepAliveInterval(keepAliveSeconds); 
     } 

     void connect() { 
      Log.i(TAG, "buttonConnect"); 
      try { 
       client.connect(options); 
      } catch (MqttException ex) { 
       Log.e(TAG, "Connection attempt failed with reason code = " + ex.getReasonCode() + ":" + ex.getCause()); 
      } 
     } 

     public boolean isConnected() { 
      return client.isConnected(); 
     } 

     public void disconnect() { 
      try { 
       client.disconnect(); 
      } catch (MqttException e) { 
       Log.e(TAG, "Disconnect failed with reason code = " + e.getReasonCode()); 
      } 
     } 

     void subscribe(String dest) { 
      try { 
       client.subscribe(dest); 
      } catch (MqttException e) { 
       Log.e(TAG, "Subscribe failed with reason code = " + e.getReasonCode()); 
      } 
     } 
    } 
} 
+0

« la connexion est reçue immédiatement après que le message a été affiché » Voulez-vous dire « la connexion est interrompue immédiatement ... » – hardillb

+0

@hardillb je l'ai fixé, merci beaucoup pour remarquer! – mjn

Répondre

2

Je suppose que c'est parce que vous essayez de mettre à jour le TextView à partir d'un thread sans interface utilisateur.

Essayez d'envelopper le messageWindow.append(msg); dans un appel runOnUiThread.

public void messageArrived(String topic, MqttMessage message) throws Exception { 
    String msg = new String(message.getPayload()); 
    Log.i(TAG, "Message Arrived: " + msg); 
    runOnUiThread(new Runnable(){ 
     public void run() { 
      messageWindow.append(msg); 
     } 
    }); 
} 
+1

Cela a résolu, merci beaucoup! (Je pensais que déplacer toute la connexion à un AsyncTask pourrait aider) – mjn

+0

Cela fonctionne, grâce à vous deux –