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"/>
Related
Hi developers in my app i perform two operation one is to connect a specific wifi by providing SSID and password programmatically and another one is interact with MQTT. Both operation work fine individually , but when first connect to WIFI programmatically and after that if i am trying to connect MQTT it throws Exception.
MqttException (0) - java.net.SocketException: socket failed: ENONET (Machine is not on the network)
1608792187.259 31589-31589/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
1608792187.259 31589-31589/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:690)
1608792187.259 31589-31589/com.asiczen.azlock W/System.err: at java.lang.Thread.run(Thread.java:919)
And here is my Wifi connection.
private void connectToBrideAboveQ(String networkSSID, String networkPass){
WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
builder.setSsid(networkSSID);
builder.setWpa2Passphrase(networkPass);
WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
networkRequestBuilder.setNetworkSpecifier(wifiNetworkSpecifier);
NetworkRequest networkRequest = networkRequestBuilder.build();
cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
networkCallback = new ConnectivityManager.NetworkCallback(){
#Override
public void onAvailable(#NonNull Network network) {
super.onAvailable(network);
Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onAvailable: "+network);
cm.bindProcessToNetwork(network);
}
};
cm.requestNetwork(networkRequest, networkCallback);
}
And here is mqtt connection code
mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setCleanSession(true);
mqttClient = new MqttAndroidClient(this, url, id);
mqttClient.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable throwable) {
doConnectTask = true;
Log.d(TAG, "MQTT connectionLost: ");
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
mqttClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken iMqttToken) {
Log.d(TAG, "MQTT CONNECTED: ");
}
#Override
public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
doConnectTask = true;
//setNewMqttClient();
throwable.printStackTrace();
Log.d(TAG, "MQTT FAILER onFailure: ");
}
});
Thanks in advance
Finally I solve this before connecting to MQTT just call cm.bindProcessToNetwork(null); this solve my problem.
I am trying to establish a websocket connection on my server. Where do I place the code to connect, reconnect if connection closed, etc, in my Android app so that if the app is closed the websocket connection will still work?
public class EchoWebSocketListener extends WebSocketListener {
#Override
public void onOpen(WebSocket webSocket, okhttp3.Response response) {
Log.d(TAG, "onOpen: Opened: " + response.toString());
}
#Override
public void onMessage(WebSocket webSocket, String text) {
Log.d(TAG, "onMessage: Recieved: " + text);
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
Log.d(TAG, "onClosing: onClosing");
}
#Override
public void onClosed(WebSocket webSocket, int code, String reason) {
Log.d(TAG, "onClosed: Closed: ");
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, okhttp3.Response response) {
Log.d(TAG, "onFailure: Failure" + t);
//createNewWebsocketConnection();
}
}
private void createNewWebsocketConnection(){
if(mUserId != null){
EchoWebSocketListener listener = new EchoWebSocketListener();
Request request = new Request.Builder()
.url(MAIN_WS_URL)
.addHeader("user_id_connection", mUserId)
.build();
OkHttpClient client = new OkHttpClient
.Builder()
.pingInterval(30, TimeUnit.SECONDS)
.build();
ws = client.newWebSocket(request, listener);
}
}
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.
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
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 !