Android - Paho MQTT для публикации

Я новичок в Android и сервисах. Моя цель - настроить подписку и делать публикации по темам. Строки темы и идентификатор клиента настраиваются после разбора ввода текстовых полей. Я использую сервис Paho MQTT (загрузил источник и построил JAR).

Ниже приведено исключение Null Pointer в c.publish(). logcat показывает исключение в методе IMqttDeliveryToken publish(String topic, MqttMessage message, Object userContext, IMqttActionListener callback) в MqttAndroidClient, где выполняется маркер доставки.

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set locale;
        l = getResources().getConfiguration().locale;
    }

    @Override
    protected void onResume() {
        super.onResume();
        addButtonListener();        
    }

    private void addButtonListener() {
        Button submitButton = (Button) findViewById(R.id.buttonSubmit);

        submitButton.setOnClickListener(new OnClickListener() {
// ...
// validation code for fields in layout
// ...
// Finally, this.

                    MemoryPersistence mPer = new MemoryPersistence();
                    String clientId = UUID.randomUUID().toString();
                    String brokerUrl = "tcp://m2m.eclipse.org:1883";
                    MqttAndroidClient c = new MqttAndroidClient(getApplicationContext(), brokerUrl, clientId, mPer);
                    try {
                        c.connect(); 
                        String topic = "transfers/topic";
                        String msg = "topic payload"
                        MqttMessage m = new MqttMessage();
                        m.setPayload(msg.getBytes());
                        m.setQos(2);
                        m.setRetained(false);
                        c.publish(topic, m); 
                    } catch (MqttException e) {
                        Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                    }

Не могли бы вы рассказать мне, как использовать услугу для публикации и подписки? Я просмотрел образец проекта (от Paho Android). LWT и публикация, похоже, объединены, поскольку макет для LWT (activity_publish.xml), по-видимому, также используется для публикации.

Ответ 1

NullPointerException заключается в том, что connect() вызывает асинхронный метод, и вам нужно реализовать ActionListener. В случае успеха вы можете отправлять сообщения.

Log.i(LOGTAG, "MQTT Start");

MemoryPersistence memPer = new MemoryPersistence();

final MqttAndroidClient client = new MqttAndroidClient(
    context, "tcp://192.168.0.13:1883", username, memPer);

try {
    client.connect(null, new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken mqttToken) {
            Log.i(LOGTAG, "Client connected");
            Log.i(LOGTAG, "Topics="+mqttToken.getTopics());

            MqttMessage message = new MqttMessage("Hello, I am Android Mqtt Client.".getBytes());
            message.setQos(2);
            message.setRetained(false);

            try {
                client.publish("messages", message);
                Log.i(LOGTAG, "Message published");

                client.disconnect();
                Log.i(LOGTAG, "client disconnected");

            } catch (MqttPersistenceException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            } catch (MqttException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            // TODO Auto-generated method stub
            Log.i(LOGTAG, "Client connection failed: "+arg1.getMessage());

        }
    });
}

Ответ 2

Очень важно понять, что вам нужно вызвать client.setCallback и реализовать MqttCallbackHandler, чтобы получать сообщения по тем, на которые вы подписаны.

Вот пример кода, который может публиковать и подписываться и т.д.

Следующий код изначально публикует тему mqtt и полезную нагрузку:

  • Тема: AndroidPhone
  • Полезная нагрузка: Привет, я клиент Android Mqtt.

Код подписывается на тему "Тестер". Если он получает сообщение с темой "тестер" и полезной нагрузкой "Alarm Activated", он публикует следующий раздел и полезную нагрузку (через обратный вызов, упомянутый выше):

  • Тема: Fitlet
  • Полезная нагрузка: Привет, брокер Mosquitto получил ваше сообщение о том, что Аварийный сигнал активирован.

Если вы используете Mosquitto, тогда следующая команда в терминале вызовет это сообщение:

mosquitto_pub -h 192.168.9.100 -t tester -m "Alarm Activated" -u fred -P 1234

Где мое имя пользователя Mosquitto - fred, а мой пароль - 1234

Код:

package colin.android.mqtt;    
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
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.MqttCallbackExtended;
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.UnsupportedEncodingException;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String clientId = MqttClient.generateClientId();

        //The URL of the Mosquitto Broker is 192.168.9.100:1883
        final  MqttAndroidClient client = new MqttAndroidClient(this.getApplicationContext(), "tcp://192.168.9.100:1883", clientId);

        client.setCallback(new MqttCallbackHandler(client));//This is here for when a message is received

        MqttConnectOptions options = new MqttConnectOptions();

        try {
            options.setUserName("fred");
            options.setPassword("1234".toCharArray());
            IMqttToken token = client.connect(options);

            token.setActionCallback(new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    // We are connected
                    Log.d("mqtt", "onSuccess");
//-----------------------------------------------------------------------------------------------
                    //PUBLISH THE MESSAGE                    
                    MqttMessage message = new MqttMessage("Hello, I am an Android Mqtt Client.".getBytes());
                    message.setQos(2);
                    message.setRetained(false);

                    String topic = "AndroidPhone";

                    try {
                        client.publish(topic, message);
                        Log.i("mqtt", "Message published");

                        // client.disconnect();
                        //Log.i("mqtt", "client disconnected");

                    } catch (MqttPersistenceException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();

                    } catch (MqttException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
//-----------------------------------------------------------------------------------------------

                    String subtopic = "tester";
                    int qos = 1;
                    try {
                        IMqttToken subToken = client.subscribe(subtopic, qos);
                        subToken.setActionCallback(new IMqttActionListener() {
                            @Override
                            public void onSuccess(IMqttToken asyncActionToken) {
                                // The message was published
                                Log.i("mqtt", "subscription success");
                            }

                            @Override
                            public void onFailure(IMqttToken asyncActionToken,
                                                  Throwable exception) {
                                // The subscription could not be performed, maybe the user was not
                                // authorized to subscribe on the specified topic e.g. using wildcards
                                Log.i("mqtt", "subscription failed");

                            }
                        });



                    } catch (MqttException e) {
                        e.printStackTrace();
                    }

//---------------------------------------------------------------------------

                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    // Something went wrong e.g. connection timeout or firewall problems
                    Log.d("mqtt", "onFailure");

                }

            });


        } catch (MqttException e) {
            e.printStackTrace();
        }

    }


}//End of Activity class

//-----------------------------------------------------------------------------

class MqttCallbackHandler implements MqttCallbackExtended {

    private final MqttAndroidClient client;

    public MqttCallbackHandler (MqttAndroidClient client)
    {
        this.client=client;
    }

    @Override
    public void connectComplete(boolean b, String s) {
        Log.w("mqtt", s);
    }

    @Override
    public void connectionLost(Throwable throwable) {

    }

    public void AlarmActivatedMessageReceived()
    {
        MqttMessage msg= new MqttMessage("Hello, the Mosquitto Broker got your message saying that the Alarm is Activated.".getBytes());
        try {
            this.client.publish("Fitlet", msg);
            Log.i("mqtt", "Message published");

        } catch (MqttPersistenceException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        } catch (MqttException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        Log.w("mqtt", mqttMessage.toString());

        if (mqttMessage.toString().contains("Alarm Activated"))
        {
            AlarmActivatedMessageReceived();
        }

    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

    }
}