使用 Paho MqttClient 在 Android 上尝试 Mqtt 连接

Trying Mqtt connection on Android using Paho MqttClient(使用 Paho MqttClient 在 Android 上尝试 Mqtt 连接)
本文介绍了使用 Paho MqttClient 在 Android 上尝试 Mqtt 连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您第一次打开应用程序时,我想要一个屏幕,您可以在其中输入经纪人信息并单击尝试并保存.

When you first open the app I want a screen where you can enter the broker information and click try and save.

当点击尝试时,它应该只显示一个 Snackbar 说明该信息是否有助于成功连接.

When clicking try it should just show a Snackbar saying if the information makes for a successful connection.

这是我按下 try 按钮时调用的代码:

This is the code I call when the try button is pressed:

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似乎在无法连接到服务器时没有被调用,而是在与服务器的连接丢失时调用.

The problem is, onFailure doesn't seem to be called when it cannot connect to the server, but when a connection to a server is lost.

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

How do I just test the connection, so I can store it and go back to the main activity?

推荐答案

好的,所以我看不到您的完整服务、任何其他实现或您如何/在何处使用它,所以我提供了我的 MQTT 示例服务.

Ok, so I can't see your full service, any other implementation or how/where you are using this so I'm providing a sample of my MQTT service.

也许你可以比较一下,发现任何问题并修复它.

Maybe you can compare it, find any issue and fix it.

或者你可以使用我的实现.由你决定.希望对您有所帮助.

Or you can just use my implementation. Up to you. Hope it helps.

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.如果连接失败,您将发送不同的广播并显示不同的消息.

My other suggestion would be to just setup local broadcast so when your activity loads and you start the service, if MQTT service is able to connect, you send a broadcast saying connected and you show a Snackbar. If connection failed, you send a different broadcast and show a different message.

这篇关于使用 Paho MqttClient 在 Android 上尝试 Mqtt 连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

How to target newer versions in .gitlab-ci.yml using auto devops (java 11 instead of 8 and Android 31 instead of 29)(如何在.gitlab-ci.yml中使用自动开发工具(Java 11而不是8,Android 31而不是29)瞄准较新的版本)
Android + coreLibraryDesugaring: which Java 11 APIs can I expect to work?(Android+core LibraryDesugering:我可以期待哪些Java 11API能够工作?)
How to render something in an if statement React Native(如何在If语句中呈现某些内容Reaction Native)
How can I sync two flatList scroll position in react native(如何在本机Reaction中同步两个平面列表滚动位置)
Using Firebase Firestore in offline only mode(在仅脱机模式下使用Firebase FiRestore)
Crash on Google Play Pre-Launch Report: java.lang.NoSuchMethodError(Google Play发布前崩溃报告:java.lang.NoSuchMethodError)