2017-02-12 59 views
1

当您第一次打开应用程序时,我想要一个屏幕,您可以在其中输入代理信息并单击尝试并保存。使用Paho MqttClient在Android上尝试使用Mqtt连接

当点击尝试时,它应该只显示一个Snackbar说如果信息成功连接。

这是当按下试按钮,我叫代码:

private void tryConnection(View v){ 
    if(verifyInputs()){ 
     Snackbar.make(v, getString(R.string.trying_connection), Snackbar.LENGTH_LONG).show(); 

     String clientId = MqttClient.generateClientId(); 
     MqttAndroidClient client = 
       new MqttAndroidClient(this.getApplicationContext(), getServerAddress(), 
         clientId); 

     try { 
      IMqttToken token = client.connect(); 
      final View vinner = v; 
      token.setActionCallback(new IMqttActionListener() { 
       @Override 
       public void onSuccess(IMqttToken asyncActionToken) { 
        // We are connected 
        Snackbar.make(vinner, "Success", Snackbar.LENGTH_LONG).show(); 

       } 

       @Override 
       public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 
        // Something went wrong e.g. connection timeout or firewall problems 
        Snackbar.make(vinner, "Fail", Snackbar.LENGTH_LONG).show(); 
       } 
      }); 
     } catch (MqttException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

的问题是,onFailure似乎并不当它不能连接到服务器被调用,但是当一个连接服务器丢失。

我该如何测试连接,以便我可以存储它并返回到主要活动?

回答

1

好吧,我看不到您的全部服务,任何其他实现或您在哪里/如何使用此服务,因此我提供了我的MQTT服务的示例。

也许你可以比较它,找到任何问题并修复它。

或者你也可以使用我的实现。由你决定。希望能帮助到你。

import android.app.Service; 
import android.content.Intent; 
import android.os.Binder; 
import android.os.Handler; 
import android.os.IBinder; 
import android.support.annotation.Nullable; 
import android.util.Log; 

import org.eclipse.paho.android.service.MqttAndroidClient; 
import org.eclipse.paho.client.mqttv3.IMqttActionListener; 
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; 
import org.eclipse.paho.client.mqttv3.IMqttToken; 
import org.eclipse.paho.client.mqttv3.MqttCallback; 
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.MqttSecurityException; 
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; 

import java.util.ArrayList; 

public class MyMqttService extends Service implements MqttCallback, IMqttActionListener { 

    private final IBinder binder = new MyBinder(); 

    private MqttAndroidClient mqttClient; 
    private MqttConnectOptions mqttConnectOptions; 
    private static final MemoryPersistence persistence = new MemoryPersistence(); 
    private ArrayList<MqttAndroidClient> lostConnectionClients; 

    private String clientId = ""; 
    private boolean isReady = false; 
    private boolean doConnectTask = true; 
    private boolean isConnectInvoked = false; 

    private Handler handler = new Handler(); 
    private final int RECONNECT_INTERVAL = 10000; // 10 seconds 
    private final int DISCONNECT_INTERVAL = 20000; // 20 seconds 
    private final int CONNECTION_TIMEOUT = 60; 
    private final int KEEP_ALIVE_INTERVAL = 200; 

    private String broker_url = "my_broker"; 

    public MyMqttService() {} 

    public class MyBinder extends Binder { 
     public MyMqttService getService() { 
      return MyMqttService.this; 
     } 
    } 

    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return binder; 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     initMqttClient(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

     disconnectClients(); 
     if (isConnectInvoked && mqttClient != null && mqttClient.isConnected()) { 
      try { 
       // unsubscribe here 
       unsubscribe("¯\\_(ツ)_/¯"); 
       mqttClient.disconnect(); 
      } catch (MqttException e) { 
       Log.e("TAG", e.toString()); 
      } 
     } 

     handler.removeCallbacks(connect); 
     handler.removeCallbacks(disconnect); 
    } 

    private void initMqttClient() { 
     if(mqttClient != null) { 
      mqttClient = null; 
     } 

     lostConnectionClients = new ArrayList<>(); 

     mqttConnectOptions = new MqttConnectOptions(); 
     mqttConnectOptions.setCleanSession(true); 
     mqttConnectOptions.setConnectionTimeout(CONNECTION_TIMEOUT); 
     mqttConnectOptions.setKeepAliveInterval(KEEP_ALIVE_INTERVAL); 

     setNewMqttClient(); 

     handler.post(connect); 
     handler.postDelayed(disconnect, DISCONNECT_INTERVAL); 
    } 

    private void setNewMqttClient() { 
     mqttClient = new MqttAndroidClient(MyMqttService.this, broker_url, clientId, persistence); 
     mqttClient.setCallback(this); 
    } 

    public Runnable connect = new Runnable() { 
     public void run() { 
      connectClient(); 
      handler.postDelayed(connect, RECONNECT_INTERVAL); 
     } 
    }; 

    public Runnable disconnect = new Runnable() { 
     public void run() { 
      disconnectClients(); 
      handler.postDelayed(disconnect, DISCONNECT_INTERVAL); 
     } 
    }; 

    private void connectClient() { 
     if(doConnectTask) { 
      doConnectTask = false; 

      try { 
       isConnectInvoked = true; 
       mqttClient.connect(mqttConnectOptions, null, this); 
      } catch (MqttException ex) { 
       doConnectTask = true; 
       Log.e("TAG", ex.toString()); 
      } 
     } 
    } 

    private void disconnectClients() { 
     if (lostConnectionClients.size() > 0) { 
      // Disconnect lost connection clients 
      for (MqttAndroidClient client : lostConnectionClients) { 
       if (client.isConnected()) { 
        try { 
         client.disconnect(); 
        } catch (MqttException e) { 
         Log.e("TAG", e.toString()); 
        } 
       } 
      } 

      // Close already disconnected clients 
      for (int i = lostConnectionClients.size() - 1; i >= 0; i--) { 
       try { 
        if (!lostConnectionClients.get(i).isConnected()) { 
         MqttAndroidClient client = lostConnectionClients.get(i); 
         client.close(); 
         lostConnectionClients.remove(i); 
        } 
       } catch (IndexOutOfBoundsException e) { 
        Log.e("TAG", e.toString()); 
       } 
      } 
     } 
    } 

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

    @Override 
    public void messageArrived(String topic, MqttMessage message) throws Exception { 
     String payload = new String(message.getPayload()); 
     // do something 
    } 

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

    @Override 
    public void onSuccess(IMqttToken iMqttToken) { 
     isReady = true; 

     // subscribe here 
     subscribe("¯\\_(ツ)_/¯"); 
    } 

    @Override 
    public void onFailure(IMqttToken iMqttToken, Throwable throwable) { 
     setNewMqttClient(); 
     isReady = false; 
     doConnectTask = true; 
     isConnectInvoked = false; 
    } 

    private void subscribe(String topic) { 
     try { 
      mqttClient.subscribe(topic, 0); 
      isReady = true; 
     } catch (MqttSecurityException mqttSexEx) { 
      isReady = false; 
     } catch (MqttException mqttEx) { 
      isReady = false; 
     } 
    } 

    private void unsubscribe(String topic) { 
     try { 
      mqttClient.unsubscribe(topic); 
     } catch (MqttSecurityException mqttSecEx) { 
      Log.e("TAG", mqttSecEx.getMessage()); 
     } catch (MqttException mqttEx) { 
      Log.e("TAG", mqttEx.getMessage()); 
     } 
    } 

    private void publish(String topic, String jsonPayload) { 
     if(!isReady) { 
      return; 
     } 

     try { 
      MqttMessage msg = new MqttMessage(); 
      msg.setQos(0); 
      msg.setPayload(jsonPayload.getBytes("UTF-8")); 
      mqttClient.publish(topic, msg); 
     } catch (Exception ex) { 
      Log.e("TAG", ex.toString()); 
     } 
    } 
} 

我的另一个建议是只安装本地广播所以,当你的活动加载和启动服务,如果MQTT服务是能够连接,您发送说法连接广播和你展示一个Snackbar。如果连接失败,则发送不同的广播并显示不同的消息。

+0

嗨!我正在使用你的服务,或者至少尝试。你能解释我怎样才能订阅?我完全失去了,已经在这个小时 –

+0

@NelsonSilva有一个MQTT的onSuccess回调。一旦与经纪人的连接成功,该方法将被调用。所以你所要做的就是在那里调用'subscribe'方法,并把你正在订阅的'topic'作为参数传入。您是否收到任何错误或任何特定问题? –

+0

其实我已经尝试了很多东西,我不知道从哪里开始。我一直在YouTube上观看视频,使用“ServiceConnection”和绑定服务,但我无法到达任何地方。当我尝试订阅时,我得到一个空对象引用上的> org.eclipse.paho.android.service.MqttAndroidClient.subscribe(java.lang.String,int)'。另外,为了使订阅我需要一个IMqttToken?我很失落,对不起......我不明白从服务内部调用方法的正确方法 –