Android paho simple explanation for subscribing to a topic - android

I am trying to create a simple android app that controls my robot. All the communication is done using mqtt and eclipse paho for android, but I am very new to the protocol. I cannot find a simple explanation of how to get data from a subscribed topic. The best one I found was HiveMQ android tutorial
but that did not explain how to get the data from the callbacks. Any assistance would be appreciated.

For android I have used Paho Android project, very simple to use, here are the steps:
Intialize a client, set required options and connect.
MqttAndroidClient mqttClient = new MqttAndroidClient(BaseApplication.getAppContext(), broker, MQTT_CLIENT_ID);
//Set call back class
mqttClient.setCallback(new MqttCallbackHandler(BaseApplication.getAppContext()));
MqttConnectOptions connOpts = new MqttConnectOptions();
IMqttToken token = mqttClient.connect(connOpts);
Subscribe to a topic.
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken arg0) {
mqttClient.subscribe("TOPIC_NAME" + userId, 2, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.d(LOG_TAG, "Successfully subscribed to topic.");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d(LOG_TAG, "Failed to subscribed to topic.");
}
});
}
#Override
public void onFailure(IMqttToken arg0, Throwable arg1) {
Log.d(LOG_TAG, errorMsg);
}
});
Define your callback handler class.
public class MqttCallbackHandler implements MqttCallbackExtended {
#Override
public void connectComplete(boolean b, String s) {
Log.w("mqtt", s);
}
#Override
public void connectionLost(Throwable throwable) {
}
#Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
Log.w("Anjing", mqttMessage.toString());
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
}
Also set following in manifest file.
<service android:name="org.eclipse.paho.android.service.MqttService" >
</service>
Would recommend visiting their project on GitHub and going through samples online.
Eclipse Paho Android
Hoping this helps. If you have more questions please visit
Android step by step guide using Eclipse Paho
Cheers !

Related

MQTT Android client not connecting to broker

I'm playing around with MQTT and Android, but I can't seem to connect the client to the broker. This is how the code looks like:
String clientId = MqttClient.generateClientId();
MqttAndroidClient client = new MqttAndroidClient(this, brokerIp, clientId);
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
Log.i(TAG, "connectionLost");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG, "messageArrived");
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i(TAG, "deliveryComplete");
}
});
client.connect().setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "Connection success");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "Connection failed: ", exception);
}
});
The problem is that none of the callbacks are ever triggered. Running mosquitto on verbose mode there are no connections coming in from this client, and checking the log I don't see any Exception raised.
I tried locally and on the cloud and it doesn't connect to any, while a client I have on the backend side can connect to both using the same host and port.
What am I missing?
Turns out the MqttService needs to be declared in the manifest to be able to bind to the Paho Android Service correctly:
<service android:name="org.eclipse.paho.android.service.MqttService"/>

Eclipse Paho MQTT client on Android, poor performance

Im trying to use Eclipse Paho MQTT client on my Android app to receive MQTT messages.
Im receiving ~100 message/second, messages are fairly small (basically small json objects). These messages are coming from Mosquitto broker.
When I subscribe to MQTT topic, and start to receive messages, my Android app UI almost freezes. I do not even do anything about the received message on messageArrived callback.
My Eclipse Paho MQTT client usage is super basic, almost the same as in Eclipse Paho example.
Is Eclipse Paho MQTT client bad on performance, or is there something I might be doing wrong?
Im using:
org.eclipse.paho.client.mqttv3:1.1.0 & org.eclipse.paho.android.service:1.1.1
Update
Below my actual code, which is part of the fragment. So in this test im just logging the received message topic. Also with out logging, I got same result, my app almost freezes.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mqttAndroidClient = new MqttAndroidClient(getActivity().getApplicationContext(), "tcp://xx.xx.xx.xx:1883", MqttClient.generateClientId());
mqttAndroidClient.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean b, String s) {
}
#Override
public void connectionLost(Throwable throwable) {
}
#Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
Log.d("Mqtt", "messageArrived " + topic);
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
}
#Override
public void onStart() {
super.onStart();
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(true);
try {
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
try {
mqttAndroidClient.subscribe("messages/#", 0);
} catch (Exception exception) {
Log.e("Mqtt", "subscribe error", exception);
}
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.e("Mqtt", "Connection onFailure ", exception);
}
});
} catch (Exception exception) {
Log.e("Mqtt", "error " + exception);
}
}
The problem is that Paho Android Service is not using own thread to handle connection so everything is done in UI thread.
I ended up using Paho MqttAsyncClient, which handles connection in own tread its own.

MqttAndroidClient - onFailure

Question
Why I am able to connect to my server over my mainActivity , but not over a fragment?
Setup
Program 1 - works...
Right now, I have two programs.
The first one is called mqtt_test which includes a MainActivity, a Button and the connection-class Mqtt. So there are no fragments.
With that program I am able to connect to my Server, subscribe and receive messages.
Code of first programm
public class mqtt {
private Context context;
private String broker = "tcp://10.34.5.134:1883";
private String clientId= "DefaultName";
private MqttAndroidClient client;
private ConnectionListener connectionListener;
private static final String TAG_MQTT= "MQTT";
public mqtt(Context context)
{
this.context = context;
}
public void connect()
{
final String clientId = MqttClient.generateClientId();
//set options
MqttConnectOptions options = new MqttConnectOptions();
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
client =
new MqttAndroidClient(context, broker,
clientId);
try {
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Log.d(TAG_MQTT, "onSuccess");
connectionListener.connected(true);
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
Log.d(TAG_MQTT, "connectionLost: ");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.d(TAG_MQTT, "messageArrived: Message: " + message.toString() + " with topic: " + topic);
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.d(TAG_MQTT, "deliveryComplete: ");
}
});
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Log.d(TAG_MQTT, "onFailure");
connectionListener.connected(false);
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
public void subscribe(final String topic, int qos)
{
if(client.isConnected())
{
try {
IMqttToken subToken = client.subscribe(topic, qos);
subToken.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// The message was published
Log.d(TAG_MQTT, "onSuccess: Subscripted with topic: " + topic);
}
#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.d(TAG_MQTT, "onFailure: The subscription failed");
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
}
public void publish(String topic, String payload, int qos)
{
byte[] encodedPayload = new byte[0];
try {
encodedPayload = payload.getBytes("UTF-8");
MqttMessage message = new MqttMessage(encodedPayload);
client.publish(topic, message);
Log.d(TAG_MQTT, "publish: Published message:" + payload + " to topic: " + topic);
} catch (UnsupportedEncodingException | MqttException e) {
e.printStackTrace();
Log.d(TAG_MQTT, "publish: Error");
}
}
public void setConnectionListener(ConnectionListener connectionListener) {
this.connectionListener = connectionListener;
}
}
Program 2 - doesn't work
In my second program I am using nearly the same code. However, I am using fragments for future business. In some fragments are buttons, which are calling the right method.
If I press the button, then the right method gets called, like in the first program.
But the program jumps over the async task. OnSucces or onFailure never gets called.
IMqttToken token = client.connect(null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// connected
Log.d(TAG_CONNECTION, "onSuccess");
connectionListener.connected(true);
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
Log.d(TAG_CONNECTION, "connectionLost: ");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.d(TAG_CONNECTION, "messageArrived: Message: " + message.toString() + " with topic: " + topic);
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.d(TAG_CONNECTION, "deliveryComplete: ");
}
});
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d(TAG_CONNECTION, "onFailure");
connectionListener.connected(false);
Log.d(TAG_CONNECTION, exception.getMessage());
}
});
Then I called the connect-method over a new thread:
#Override
public void doSmth() {
new Thread(new Runnable() {
public void run() {
// a potentially time consuming task
mqttConnection.connect();
}
}).start();
}
Finally I got an answer:
D/CONNECTION: cannot start service org.eclipse.paho.android.service.MqttService
I don't understand why this doesn't work. Maybe you have some input.
To be clear: Both programs do have the same permissions:
<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" />
Assumption
I think, I have to use more asycTasks to solve this problem.
Input/links
It would be awesome, if you could share some links. In the best case with some examples. I only found examples wich are running in a single MainActivity.
The error
D/CONNECTION: cannot start service org.eclipse.paho.android.service.MqttService
possibly indicates that the entry
<service android:name="org.eclipse.paho.android.service.MqttService">
</service>
in AndroidManifest.xml is missing

smack 4.1 processMessage method does not called

i'm using smack 4.1 library where i'm unable to revived message event.
here is my code-
Chat chat = connection.getChatManager().createChat("user2#openfireserver", new MessageListener() {
#Override
public void processMessage(Chat arg0, Message arg1) {
System.out.println(arg1.getBody());
}
});
chat.sendMessage("test message");
debug report-
<message id="WrfOv-14" to="user1#openfireserver/Smack" from="user2#openfireserver/Smack" type="chat"><body>my test application</body><thread>56b1a75c-69a5-4a12-b12a-d24e072a2ce7</thread></message>
receive chat show in debug but not getting event in processMessage method.
(may my question is duplicate but i'm not find relevant answer)
I have used Smack 4.1 library in one of my Android projects. The following code snippet worked for me.
ChatManager.getInstanceFor(connection).addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean createdLocally) {
chat.addMessageListener(new ChatMessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
if (message.getType() == Message.Type.chat || message.getType() == Message.Type.normal) {
if(message.getBody()!=null) {
Toast.makeText(this,message.getFrom() + " : " + message.getBody(),Toast.LENGTH_LONG).show();
}
}
}
});
}
});
Here is an example for smack-4.1.0-beta3-SNAPSHOT-2015-02-09:
It works for me, try it.
private void onAutthenticated() {
ChatManager.getInstanceFor(mConnection).addChatListener(ChatConnection.this);
}
#Override
public void chatCreated(Chat chat, boolean b) {
chat.addMessageListener(new ChatMessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
if (message.getType().equals(Message.Type.chat) || message.getType().equals(Message.Type.normal)) {
Log.d(TAG, message.getFrom());
Log.d(TAG, message.getBody());
}
}
});
}
For Receiving any Type of Message, you can use following code
StanzaTypeFilter message_filter = new StanzaTypeFilter(Message.class);
connection.addSyncStanzaListener(new StanzaListener() {
#Override
public void processPacket(Stanza packet) throws NotConnectedException {
Message message = (Message)packet;
if(message.getType() == Message.Type.chat) {
//single chat message
} else if(message.getType() == Message.Type.groupchat) {
//group chat message
} else if(message.getType() == Message.Type.error) {
//error message
}
}
}, message_filter);
I think the create methord and the add methord are not same. create methord does not register a listener,but the add methord does register.When I see the api doc, I have the same question with you,but the doc does not give me an answer.So i guess this may be where the problem exists.

registration-required(407) Error Quickblox android

When I am trying to call joinRoom() or createRoom() method.I am getting two different error
"registration-required(407)"
"feature-not-implemented(501) Will me done soon".
for reference purpose,I have posted code also.I already posted this issue on quickblox discussion board but nobody has solution.
QBChatService.getInstance().joinRoom(roomName, roomReceivingListener);
String roomName="myroom";
roomReceivingListener = new RoomListener()
{
#Override
public void onCreatedRoom(QBChatRoom qbChatRoom)
{
Log.i("TAG", "on Created Room listener");
chatRoom = qbChatRoom;
//chatRoom.addMessageListener(chatMessageListener);
}
#Override
public void onJoinedRoom(QBChatRoom qbChatRoom)
{
Log.i("TAG", "on Joined Room listener");
chatRoom = qbChatRoom;
//QBChatService.getInstance().joinRoom(chatRoom, roomReceivingListener);
//chatRoom.addMessageListener(chatMessageListener);
}
#Override
public void onError(String msg)
{
Log.i("TAG", "on join Room error listener");
}
};

Categories

Resources