I just start use MQTT Paho library in my app.
How to make an asynchronous subscription to the topic? (subscription in new thread)
And then in real time to receive the data and display.
It's my code in MainActivity, in main thread:
public void mqttConnect () {
final TextView textView = (TextView) findViewById(R.id.sub_Text_View);
String clientId = MqttClient.generateClientId();
final MqttAndroidClient client = new MqttAndroidClient(this.getApplicationContext(), server, clientId);
client.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean reconnect, String serverURI) {
}
#Override
public void connectionLost(Throwable cause) {
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.d("NANADEV", message.toString());
textView.setText(message.toString());
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(false);
try {
client.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
final String topic = "testwork/value";
int qos =0;
try {
IMqttToken subToken = client.subscribe(topic, qos);
subToken.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
}
});
} catch (MqttException e) {
e.printStackTrace();
}
Thanks!
In your oncreate
private String uniqueID;
String ip="brokerip";
String port="brokerport usaly 1883"
String broker = "tcp://" + ip + ":" + port;
uniqueID = android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
IMqttAsyncClient client= new MqttAsyncClient(broker, uniqueID, new MemoryPersistence());
mqttClient.subscribe("YOURTOPIC/", 0);
mqttClient.subscribe("YOUROTHERTOPIC", 0);
and then in your method:
public void messageArrived(String topic, MqttMessage msg) throws Exception {
Log.i("mqttarrival", "Message arrived from topic " + topic);
if (topic.equals("YOURTOPIC")) {
System.out.println(msg.toString());
}
else {
}
}
Related
using mqtt for push notification in android with following libs :
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
i followed this tutorial , the problem is it works properly when app is open , but when it is swiped from recent apps , it stops working and I can't receive push notifications anymore
any help is appreciated
solutions i tried :
first solution : created a service and simply created a mqttclient in it , but after swiping from recent apps didn't work anymore
public class MqttService extends Service {
public MqttService(Context context) {
super();
}
public MqttService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
PahoDemo paho = new Paho(getApplicationContext(), "myTopic");
return START_STICKY;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent intent = new Intent("com.example.restart");
sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
Intent intent = new Intent("com.example.restart");
sendBroadcast(intent);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
PahoDemo :
public class Paho implements MqttCallback {
String topic;
MqttClient client;
Context context;
public Paho(Context context, String topic) {
this.context = context;
this.topic = topic;
try {
client = new MqttClient(StaticValue.getBROKER(), MqttClient.generateClientId(), persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
client.connect(connOpts);
client.setCallback(this);
if (topic != null) {
client.subscribe(topic);
}
} catch (MqttException e) {
System.out.println("error: " + e);
e.printStackTrace();
}
}
#Override
public void connectionLost(Throwable cause) {
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i("mqtt", "messageArrived ");
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i("mqtt", token + "");
}
}
second solution:
added the below line to manifest :
<service android:name="org.eclipse.paho.android.service.MqttService" />
called this helper class from mainactivty's Oncreate :
public class MqttHelper {
public MqttAndroidClient mqttAndroidClient;
final String serverUri = "myBrokerUri";
final String clientId = MqttClient.generateClientId();
final String subscriptionTopic = "myTopic";
public MqttHelper(Context context){
mqttAndroidClient = new MqttAndroidClient(context, serverUri, clientId);
mqttAndroidClient.setCallback(new 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("Mqtt", mqttMessage.toString());
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
connect();
}
public void setCallback(MqttCallbackExtended callback) {
mqttAndroidClient.setCallback(callback);
}
private void connect(){
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(true);
try {
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
subscribeToTopic();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.w("Mqtt", "Failed to connect to: " + serverUri + exception.toString());
}
});
} catch (MqttException ex){
ex.printStackTrace();
}
}
private void subscribeToTopic() {
try {
mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.w("Mqtt","Subscribed!");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.w("Mqtt", "Subscribed fail!");
}
});
} catch (MqttException ex) {
System.err.println("Exceptionst subscribing");
ex.printStackTrace();
}
}
}
that's all i did since tow days ago . if someone has any ideas , please mention .
when messageArrived is called , you shouldn't use something you don't access to . for example if you wanna check app is in foreground , you may use context , this way your logic may doesn't work properly , so make sure you do what you can do in messageArrived and if you aren't sure the objects you use are available do it another way (also be careful about connectinLost )
Can this library give opportunity make connections for several servers?
https://github.com/eclipse/paho.mqtt.android
I can not figure this case out the source code
For example:
mqttAndroidClient1 = new MqttAndroidClient(getApplicationContext(), "tcp://iot.eclipse.org:1883", clientId);
mqttAndroidClient2 = new MqttAndroidClient(getApplicationContext(), "tcp://iot.blablabla.org:1883", clientId);
....
mqttAndroidClient1.connect(...)
mqttAndroidClient2.connect(...)
Ok. It's work. I tested through my locale device and this service https://iot.eclipse.org/getting-started#sandboxes.
public class MainActivity extends AppCompatActivity {
private final String TAG = this.getClass().getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Handler mHandler = new Handler();
MqttAndroidClient mqttAndroidClient1;
MqttAndroidClient mqttAndroidClient2;
String clientId = "ExampleAndroidClient";
final String serverUri = "tcp://iot.eclipse.org:1883";
final String serverUri2 = "tcp://192.168.10.11:1883" ;
#Override
protected void onStart() {
super.onStart();
clientId = clientId + System.currentTimeMillis();
mqttAndroidClient2 = new MqttAndroidClient(getApplicationContext(), serverUri2, clientId+"2");
mqttAndroidClient2.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean reconnect, String serverURI) {
if (reconnect) {
Log.i(TAG,"Reconnected to : " + serverURI);
// Because Clean Session is true, we need to re-subscribe
subscribeToTopic2();
} else {
Log.i(TAG,"Connected to: " + serverURI);
}
}
#Override
public void connectionLost(Throwable cause) {
Log.w(TAG,"The Connection was lost.");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG,"Incoming message: " + new String(message.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
mqttAndroidClient1 = new MqttAndroidClient(getApplicationContext(), serverUri, clientId);
mqttAndroidClient1.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean reconnect, String serverURI) {
if (reconnect) {
Log.i(TAG,"Reconnected to : " + serverURI);
// Because Clean Session is true, we need to re-subscribe
subscribeToTopic1();
} else {
Log.i(TAG,"Connected to: " + serverURI);
}
}
#Override
public void connectionLost(Throwable cause) {
Log.w(TAG,"The Connection was lost.");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG,"Incoming message: " + new String(message.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(false);
try {
//addToHistory("Connecting to " + serverUri);
mqttAndroidClient1.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setBufferSize(100);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
mqttAndroidClient1.setBufferOpts(disconnectedBufferOptions);
subscribeToTopic1();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.e(TAG,"Failed to connect to: " + mqttAndroidClient1.getServerURI());
}
});
} catch (MqttException ex){
ex.printStackTrace();
}
try {
//addToHistory("Connecting to " + serverUri);
mqttAndroidClient2.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setBufferSize(100);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
mqttAndroidClient2.setBufferOpts(disconnectedBufferOptions);
subscribeToTopic2();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.e(TAG,"Failed to connect to: " + mqttAndroidClient2.getServerURI());
}
});
} catch (MqttException ex){
ex.printStackTrace();
}
}
#Override
protected void onStop() {
super.onStop();
}
public void subscribeToTopic1(){
String subscriptionTopic = "/uwblogs";
try {
mqttAndroidClient1.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG,"Subscribed!");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG,"Failed to subscribe");
}
});
mqttAndroidClient1.subscribe(subscriptionTopic, 0, new IMqttMessageListener() {
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
// message Arrived!
final String str = new String(message.getPayload());
mHandler.post(new Runnable() {
#Override
public void run() {
((TextView)findViewById(R.id.textView_server1)).setText(str);
}
});
Log.i(TAG,"Message: " + topic + " : " + new String(message.getPayload()));
}
});
} catch (MqttException ex){
System.err.println("Exception whilst subscribing");
ex.printStackTrace();
}
}
public void subscribeToTopic2(){
String subscriptionTopic = "/devices/wb-adc/controls/Vin";
try {
mqttAndroidClient2.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG,"Subscribed!");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG,"Failed to subscribe");
}
});
mqttAndroidClient2.subscribe(subscriptionTopic, 0, new IMqttMessageListener() {
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
// message Arrived!
final String str = new String(message.getPayload());
mHandler.postAtFrontOfQueue(new Runnable() {
#Override
public void run() {
((TextView)findViewById(R.id.textView_server2)).setText(str);
}
});
Log.i(TAG,"Message server2: " + topic + " : " + new String(message.getPayload()));
}
});
} catch (MqttException ex){
System.err.println("Exception whilst subscribing");
ex.printStackTrace();
}
}
}
I am new into MQTT and PAHO MQTT Client library too. I can connect successfully but when I subscribe I am not able to get the success message. Here is my code
String topic = "test123";
int qos = 2;
try {
IMqttToken subToken = client.subscribe(topic, qos);
subToken.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// The message was published
}
#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
}
});
} catch (MqttException e) {
e.printStackTrace();
}
public void subscribeMqttChannel(String channelName) {
try {
Log.d("tag","mqtt channel name>>>>>>>>" + channelName);
Log.d("tag","client.isConnected()>>>>>>>>" + client.isConnected());
if (client.isConnected()) {
client.subscribe(channelName, 0);
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable cause) {
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.d("tag","message>>" + new String(message.getPayload()));
Log.d("tag","topic>>" + topic);
parseMqttMessage(new String(message.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
}
} catch (Exception e) {
Log.d("tag","Error :" + e);
}
}
I am trying to learn basic MQTT integration in Android. I am using a mosquitto broker to publish and subscribe messages. I am running the code on a real device and getting this exception :
Unable to connect to server (32103) - java.net.ConnectException:
failed to connect to /192.168.0.103 (port 1883) after
30000ms: isConnected failed: ECONNREFUSED
Here's my code:
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://192.168.0.103: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());
}
}
}
I've tried using different ports but the error is same. Can anyone help what am i doing wrong?
As you are getting started, you need to see see how different implementations work. Take a look at my implementation. I use a separated class for MQTT specific stuff.
MqttUtil.java
public class MqttUtil {
private static final String MQTT_TOPIC = "test/topic";
private static final String MQTT_URL = "tcp://localhost:1883";
private static boolean published;
private static MqttAndroidClient client;
private static final String TAG = MqttUtil.class.getName();
public static MqttAndroidClient getClient(Context context){
if(client == null){
String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(context, MQTT_URL, clientId);
}
if(!client.isConnected())
connect();
return client;
}
private static void connect(){
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setCleanSession(true);
mqttConnectOptions.setKeepAliveInterval(30);
try{
client.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.d(TAG, "onSuccess");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d(TAG, "onFailure. Exception when connecting: " + exception);
}
});
}catch (Exception e) {
Log.e(TAG, "Error while connecting to Mqtt broker : " + e);
e.printStackTrace();
}
}
public static void publishMessage(final String payload){
published = false;
try {
byte[] encodedpayload = payload.getBytes();
MqttMessage message = new MqttMessage(encodedpayload);
client.publish(MQTT_TOPIC, message);
published = true;
Log.i(TAG, "message successfully published : " + payload);
} catch (Exception e) {
Log.e(TAG, "Error when publishing message : " + e);
e.printStackTrace();
}
}
public static void close(){
if(client != null) {
client.unregisterResources();
client.close();
}
}
}
And you can simply use it in your HomeActivity. Check it below:
public class HomeActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get Mqtt client singleton instance
MqttUtil.getClient(this);
// Publish a sample message
MqttUtil.publishMessage("Hello Android MQTT");
}
}
For testing purposes, use your Mosquitto sub client and see if you get the message.
Hope that helps!
try using port 8883
String clientId = MqttClient.generateClientId();
final MqttAndroidClient client =
new MqttAndroidClient(this.getApplicationContext(), "ssl://iot.eclipse.org:8883",
clientId);
try {
MqttConnectOptions options = new MqttConnectOptions();
InputStream input =
this.getApplicationContext().getAssets().open("iot.eclipse.org.bks");
options.setSocketFactory(client.getSSLSocketFactory(input, "eclipse-password"));
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Log.d(TAG, "onSuccess");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Log.d(TAG, "onFailure");
}
});
} catch (MqttException | IOException e) {
e.printStackTrace();
}
Client side code:
private void startPolling() {
final String wsuri = MainAsync.WEB_SOCKET_HOST_WS+"/game";
try {
mConnection.connect(wsuri, new WebSocketHandler() {
#Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri);
int role = mAccMeth.loadId(getApplicationContext());
mConnection.sendTextMessage(String.valueOf(role));
}
#Override
public void onTextMessage(String payload) {
Log.d(TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.d(TAG, "Connection lost.");
}
});
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
}
Server side realisation:
#ServerEndpoint(value="/game",configurator = ServletConfig.class)
public class WebSocketPollingCoordinates {
EndpointConfig endConfig;
#OnMessage
public void receiveMessage(String message,final Session session){
HttpSession httpSession = (HttpSession) endConfig.getUserProperties().get("httpSession");
//at this line i get NullpointerException
final ServletContext sercntxt = (ServletContext)httpSession.getServletContext();
}
#OnOpen
public void onOpen(Session sn, EndpointConfig ec) {
System.out.println("onOpen");
this.endConfig = ec;
}
#OnError
public void error(Session session, Throwable t) {
t.printStackTrace();
}
And WebSocket Config class:
public class ServletConfig extends Configurator{
#Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
if(httpSession==null || config==null){
if(httpSession==null)
System.out.println("httpSession==null");
if(config==null)
System.out.println("config==null");
return;
}
config.getUserProperties().put("httpSession", httpSession);
}
}
I'm always getting next out: http session == null. Where is the error? I need to get httpSession, to call void httpSession.getServletContext();