[英]Trying Mqtt connection on Android using Paho MqttClient
When you first open the app I want a screen where you can enter the broker information and click try and save.当您第一次打开应用程序时,我想要一个屏幕,您可以在其中输入经纪人信息,然后单击尝试并保存。
When clicking try it should just show a Snackbar
saying if the information makes for a successful connection.单击尝试时,它应该只显示一个
Snackbar
说明该信息是否有助于成功连接。
This is the code I call when the try button is pressed:这是我按下 try 按钮时调用的代码:
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();
}
}
}
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.问题是,当无法连接到服务器时,似乎不会调用
onFailure
,而是当与服务器的连接丢失时。
How do I just test the connection, so I can store it and go back to the main activity?我如何只测试连接,以便我可以存储它并返回到主要活动?
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.好的,所以我看不到您的完整服务、任何其他实现或您使用它的方式/地点,因此我提供了我的 MQTT 服务示例。
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());
}
}
}
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
.我的另一个建议是只设置本地广播,这样当您的活动加载并启动服务时,如果 MQTT 服务能够连接,您发送一个广播说已连接并显示
Snackbar
。 If connection failed, you send a different broadcast and show a different message.如果连接失败,您将发送不同的广播并显示不同的消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.