5

I have just started learning using MQTT protocol with Android Studio. Using mosquitto broker, I am able to exchange messages between pub/sub windows. But when I send message to broker through android studio, the app builds successfully but nothing displays on broker's end & system prints Connection Failure. The same code works fine on eclipse java application, but not working on android although required libraries and dependencies have been added.

Please help, what am I missing in this basic step so i can learn forward. Thank you!

app-build.gradle

    dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.2.0'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'

// have added following dependencies

    provided 'com.google.android.things:androidthings:0.2-devpreview'
    provided 'com.google.android.things:androidthings:0.1-devpreview'
    compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.0.2'

}

project-build.gradle

   repositories {
            jcenter()
            maven {
                url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
            }    
}

AndroidManifest.xml

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.zoha.mqttandroidiot">

    <!-- Permissions the Application Requires -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">


        <activity android:name=".HomeActivity">

            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <!-- Launch activity automatically on boot -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.IOT_LAUNCHER"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

        </activity>
<service android:name="org.eclipse.paho.android.service.MqttService"/>

    </application>

</manifest>

HomeActivity

  public class HomeActivity extends AppCompatActivity{

    MqttAndroidClient client;
   // private static final MemoryPersistence persistence = new MemoryPersistence();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final MqttAndroidClient mqttAndroidClient = new MqttAndroidClient(this.getApplicationContext(), "tcp://localhost:1883", "androidSampleClient");
        mqttAndroidClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                System.out.println("Connection was lost!");

            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                System.out.println("Message Arrived!: " + topic + ": " + new String(message.getPayload()));

            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                System.out.println("Delivery Complete!");
            }
        });

        try {
            mqttAndroidClient.connect(null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    System.out.println("Connection Success!");
                    try {
                        System.out.println("Subscribing to /test");
                        mqttAndroidClient.subscribe("/test", 0);
                        System.out.println("Subscribed to /test");
                        System.out.println("Publishing message..");
                        mqttAndroidClient.publish("/test", new MqttMessage("Hello world testing..!".getBytes()));
                    } catch (MqttException ex) {

                    }

                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    System.out.println("Connection Failure!");
                }
            });
        } catch (MqttException ex) {

        }


    }
    }
Noor
  • 193
  • 1
  • 2
  • 15
  • Also, make sure to fix the `service` tags in your `AndroidManifest.xml` file. `service..` tag should be outside your `activity` tag. So copy the `‹service..` line and paste it below the `` line – ᴛʜᴇᴘᴀᴛᴇʟ Mar 27 '17 at 05:49
  • Change the BROKER url to your system ip address not your mobile's ip. – Prasad Jul 05 '18 at 10:34

4 Answers4

4

I wanted to just add a comment, but my rep is too low...so i'm posting it as an answer.

You said you got everything working but are unable to connect because of the IllegalArgumentException. I had the same problem and found out that you need to define the protocol also. So instead of "192.168.0.103:1883" try:

String serverURI = "tcp://192.168.0.103:1883"

From what i read you already did the other necessary steps, but for the sake of giving a complete answer:

  1. Edit the AndroidManifest.xml to include:

    • <service android:name="org.eclipse.paho.android.service.MqttService" /> (from inside the application tag)

    • <uses-permission android:name="android.permission.INTERNET" />

    • <uses-permission android:name="android.permission.WAKE_LOCK" />
    • <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  2. Edit the build.gradle to include (in the dependencies section):

    • compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1'

    • compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

  3. Use the MqttAndroidClient (not the MqttClient)

  4. Put your code in the "onSuccess" callback, to avoid any problems due to the methods being asynchronous (as shown by THEPATEL's answer):

    MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
    mqttConnectOptions.setKeepAliveInterval(60);//seconds
    mqttConnectOptions.setCleanSession(true);
    mqttConnectOptions.setAutomaticReconnect(true);
    
    mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {
                //Treat success here (subscribe, publish etc)
            }
    
            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                //Treat failure here
            }
        });
    
F. ALA
  • 913
  • 8
  • 10
3

Ok so you need two libraries to use MQTT in Android. One is the mqtt paho client and other being Android service library.

compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.0.2'
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.0.2'

Then, use MqttAndroidClient instead of MqttClient.

So do new MqttAndroidClient(...).

I posted a full Android MQTT service example here, if that helps.

EDIT: full activity example

(1) MemoryPersistence added when creating new MqttAndroidClient.
(2) Two parameters added to .connect() method of the MqttAndroidClient (mqttConnectOptions and null).
(3) Also, printing the error on onFailure()

public class HomeActivity extends AppCompatActivity {

    private MqttAndroidClient client;
    private final MemoryPersistence persistence = new MemoryPersistence();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final MqttAndroidClient mqttAndroidClient = new MqttAndroidClient(this.getApplicationContext(), "tcp://localhost:1883", "androidSampleClient", persistence);
        mqttAndroidClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                System.out.println("Connection was lost!");
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                System.out.println("Message Arrived!: " + topic + ": " + new String(message.getPayload()));
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                System.out.println("Delivery Complete!");
            }
        });

        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setCleanSession(true);

        try {
            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    System.out.println("Connection Success!");
                    try {
                        System.out.println("Subscribing to /test");
                        mqttAndroidClient.subscribe("/test", 0);
                        System.out.println("Subscribed to /test");
                        System.out.println("Publishing message..");
                        mqttAndroidClient.publish("/test", new MqttMessage("Hello world testing..!".getBytes()));
                    } catch (MqttException ex) {

                    }
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    System.out.println("Connection Failure!");
                    System.out.println("throwable: " + exception.toString());
                }
            });
        } catch (MqttException ex) {
            System.out.println(ex.toString());
        }
    }
}
Community
  • 1
  • 1
ᴛʜᴇᴘᴀᴛᴇʟ
  • 4,466
  • 5
  • 39
  • 73
  • Thank you for your help. But now its giving null pointer exception on publish statement: 'org.eclipse.paho.client.mqttv3.IMqttDeliveryToken org.eclipse.paho.android.service.MqttService.publish(java.lang.String, java.lang.String, org.eclipse.paho.client.mqttv3.MqttMessage, java.lang.String, java.lang.String)' on a null object reference – Noor Mar 27 '17 at 06:33
  • @Noor can you debug and find out which one of the parameter is null? If anything, just try to print each parameter in log and see which one is null. I seems like a very simple issue – ᴛʜᴇᴘᴀᴛᴇʟ Mar 27 '17 at 11:39
  • @th3pat3I Can you please see the revised code? It's now giving no error & but says Connection Failure. – Noor Mar 29 '17 at 10:42
  • @Noor i posted a sample. give it a try – ᴛʜᴇᴘᴀᴛᴇʟ Mar 29 '17 at 13:56
  • @th3pat3I Thank you so much for your quick response. With your sample, connection fails with the message: unable to connect to server (32103) - java.net.connectException: failed to connect to localhost/127.0.0.1(port 1883) after 3000ms: isConnected failed: ECONNREFUSED (connection refused) ). I also tried "192.168.0.103:1883" as broker address which is my pc's ip address then it gives java.lang.IllegalArgumentException: 192.168.0.103:1883. Still trying to resolve it. – Noor Mar 30 '17 at 10:00
0

I had the same issue with MQTT publisher from an android device. While referring to tcp://localhost:1883 from an android emulator, I had to use http://10.0.2.2:1883 since emulator runs on its own VM and localhost would be emulators own loopback address.

ajroot
  • 93
  • 1
  • 1
  • 7
0

I was getting Same Error but I have solved it. This is working code.

in gradle :

compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
    compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.0'

In Manifest :

  <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

Service Tag inside Application:

  <service android:name="org.eclipse.paho.android.service.MqttService" >
        </service>

Activity Code :

 MqttAndroidClient client;
 Button btnsub,btnpublish;

to connect with Mqtt client:

String clientId = MqttClient.generateClientId();
   client = new MqttAndroidClient(getApplicationContext(), "tcp://www.domain.in/ip:11883",clientId);
        client.connect().setActionCallback(new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {
                // We are connected
            }
            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
            }
        });

To SubScribe on button click :

   client.subscribe("topic", 0, null, new IMqttActionListener() {
                        @Override
                        public void onSuccess(IMqttToken asyncActionToken) {
                        }
                        @Override
                        public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        }
                    });
                    client.subscribe("topic", 0, new IMqttMessageListener() {
                        @Override
                        public void messageArrived(String topic, MqttMessage message) throws Exception {
                        }
                    });

to Publish on button click :

   MqttMessage message = new MqttMessage();
                    message.setPayload("message".getBytes());
                    client.publish("topic", message);
Maulik Patel
  • 717
  • 1
  • 10
  • 22