-
Notifications
You must be signed in to change notification settings - Fork 925
Description
I've been developing some apps with MQTT communications and have encountered a problem on Android with the Paho library. I had a couple of apps that were functioning fine until the latest update to the "io.github.mayzs:paho.mqtt.android:1.2.3" library. I use Android Studio for development and, when I updated to this version from version 1.2.1, Mqtt stopped communication. When I connect, the IMqttActionListener does not get called on either the onSuccess or the onFailure methods, although the client seems to be connected. Further, I am able to subscribe and publish but no messages ever arrive at the callback. Published messages do get to the target client and, although the target client is working and replies, nothing arrives at the Android device. If I simply downgrade the version to 1.2.1, everything works correctly.
Here is a program I used to test this.
This is the build gradel.
plugins {
alias(libs.plugins.android.application)
}
android {
namespace = "com.gelbintergalactic.mqtttest"
compileSdk = 36
defaultConfig {
applicationId = "com.gelbintergalactic.mqtttest"
minSdk = 35
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
implementation(libs.lifecycle.service)
implementation(libs.work.runtime)
implementation(libs.appcompat)
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
implementation(libs.org.eclipse.paho.client.mqttv3)
implementation("io.github.mayzs:paho.mqtt.android:1.2.1")
}
Here is the Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MqttTest">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="org.eclipse.paho.android.service.MqttService"/>
</application>
</manifest>
Here is the MainActivity
package com.gelbintergalactic.mqtttest;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
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.MqttClient;
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.MqttPersistenceException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
MqttAndroidClient mqttClient;
String broker = "tcp://test.mosquitto.org";
boolean brokerDisconnected = true;
String deviceID = "RainTotals";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
mqttConnect(this, broker);
Runnable runnable = () -> {
do {
// Get yearly and seasonal totals
try {
if (mqttClient != null && mqttClient.isConnected()) {
byte[] payload = {0};
payload = deviceID.getBytes(StandardCharsets.UTF_8);
mqttClient.publish("RainGauge0\\sendData", payload, 0, false);
}
}
catch(MqttException e){
String errorMsg = e.getLocalizedMessage();
}
catch(Exception ignored){
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
String errorMsg = e.getLocalizedMessage();
}
if( !mqttClient.isConnected() ){
mqttConnect(getBaseContext(), broker); // Reconnect
}
} while (true);
};
new Thread(runnable).start();
}
private boolean mqttConnect(Context context, String brokeraddr) {
String clientID = MqttClient.generateClientId();
mqttClient = new MqttAndroidClient(context, brokeraddr, clientID);
MqttConnectOptions opts = new MqttConnectOptions();
//opts.setConnectionTimeout(30);
//opts.setAutomaticReconnect(true);
opts.setKeepAliveInterval(20);
try {
mqttClient.connect( opts, context, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
brokerDisconnected = false;
mqttSetReceiveListener();
mqttSubscribe("yearly", 0);
byte[] payload = {0};
String deviceID = "RainTotals";
payload = deviceID.getBytes(StandardCharsets.UTF_8);
try {
mqttClient.publish("RainGauge0\\sendData", payload, 0, false );
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
brokerDisconnected = true;
}
});
return !brokerDisconnected; // Successful connection
} catch (MqttException e) {
return false; // Connection failure
}
catch (Exception e){
return false;
}
}
private boolean mqttSubscribe( String topic, int qos ) {
String topicString = String.format(Locale.getDefault(), "RainTotals\\%s", topic);
try{
mqttClient.subscribe(topicString, qos);
return true;
}
catch( MqttException e ) {
return false;
}
catch( Exception e ){
Log.e("mqtt", e.getMessage());
return false;
}
}
private void mqttSetReceiveListener(){
mqttClient.setCallback(
new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
return;
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
try {
if( topic.contains("yearly")){
String msg = new String(message.getPayload());
String x = msg;
}
}
catch(Exception e){
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
}
);
}
}
I run Android Studio on a Windows 11 computer and run the app on a Google Pixel 8 pro. I use the test.mosquito.org Mqtt broker and this app communicates with a Windows app using M2Mqtt. Thanks for listening.