I'm implement Autobahn to connnect to a server through WebSockets. When I hit connect, it opens the socket correctly and logs that socket is opened. I then try to send a request to the server which is simply {"request":"getSoftwareVersion"} , when the server receives this, it should send back the software version in a JSON object, the trouble is, that onMessage is never hit. Here is my code:
public class AutoBahnConnectRequest extends Request{
private static WebSocketConnection mAutoBahnConnection;
private String mSocketHostAddress;
private final static String m_TAG = AutoBahnConnectRequest.class.getSimpleName();
public AutoBahnConnectRequest(String SocketHostAddress){
this.mAutoBahnConnection = new WebSocketConnection();
this.mSocketHostAddress = SocketHostAddress;
}
#Override
protected Void doInBackground(Void... params){
try {
mAutoBahnConnection.connect(mSocketHostAddress, new WebSocketHandler(){
#Override
public void onOpen() {
String requestSoftware = "{\"request\":\"getSoftwareVersion\"}";
Log.i(m_TAG, requestSoftware);
Log.i(m_TAG, "Status: Connected to " + mSocketHostAddress);
mAutoBahnConnection.sendTextMessage(requestSoftware);
}
#Override
public void onTextMessage(String payload) {
Log.i(m_TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.i(m_TAG, "Connection lost."+ reason);
}
});
} catch (WebSocketException e) {
Log.d(m_TAG, e.toString());
}
return null;
}
}
This has been implemented with a html client like so (not with autobahn):
function getSoftwareVersion() {
socket_di.send('{"request":"getSoftwareVersion"}');
}
and the onMessage receives the data. Can someone please tell me if I'm doing something wrong here?
Thank you.
I have figured out my issue regarding this. The WebSocket connection required a protocol and options to be added. So I changed this:
mAutoBahnConnection.connect(mSocketHostAddress, new WebSocketHandler(){
#Override
public void onOpen() {
String requestSoftware = "{\"request\":\"getSoftwareVersion\"}";
Log.i(m_TAG, requestSoftware);
Log.i(m_TAG, "Status: Connected to " + mSocketHostAddress);
mAutoBahnConnection.sendTextMessage(requestSoftware);
}
#Override
public void onTextMessage(String payload) {
Log.i(m_TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.i(m_TAG, "Connection lost."+ reason);
}
});
} catch (WebSocketException e) {
Log.d(m_TAG, e.toString());
}
to this:
mAutoBahnConnection.connect(mSocketHostAddress,new String[]{"this is my protocol"} ,new WebSocketHandler(){
#Override
public void onOpen() {
String requestSoftware = "{\"request\":\"getSoftwareVersion\"}";
Log.i(m_TAG, requestSoftware);
Log.i(m_TAG, "Status: Connected to " + mSocketHostAddress);
mAutoBahnConnection.sendTextMessage(requestSoftware);
}
#Override
public void onTextMessage(String payload) {
Log.i(m_TAG, "Got echo: " + payload);
}
#Override
public void onRawTextMessage(byte[] payload) {
try {
rawText = new String(payload, "UTF-8");
Log.i(m_TAG, "ON RAW TEXT");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
#Override
public void onBinaryMessage(byte[] payload) {
Log.i(m_TAG, "ON BINARY MESSAGE");
}
#Override
public void onClose(int code, String reason) {
Log.i(m_TAG, "Connection lost."+ reason);
}
}, options);
} catch (WebSocketException e) {
Log.d(m_TAG, e.toString());
}
Related
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);
}
}
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'm developing a simple WebSocket in Android using AndroidAsync library:
http://www.koushikdutta.com/AndroidAsync
My Client code:
private void conectar() {
//String uri = "ws://192.167.101.142:1234";
String uri = "http://192.167.101.166:1234";
AsyncHttpClient asyncHttpClient = AsyncHttpClient.getDefaultInstance();
//asyncHttpClient.websocket(new AsyncHttpGet(uri), "my-protocol", new AsyncHttpClient.WebSocketConnectCallback() {
//asyncHttpClient.websocket(uri, "https", new AsyncHttpClient.WebSocketConnectCallback() {
//asyncHttpClient.websocket(new AsyncHttpGet(uri), null, new AsyncHttpClient.WebSocketConnectCallback() {
//asyncHttpClient.websocket(new AsyncHttpGet(uri), "SSL", new AsyncHttpClient.WebSocketConnectCallback() {
asyncHttpClient.websocket(uri, null, new AsyncHttpClient.WebSocketConnectCallback() {
#Override
public void onCompleted(Exception ex, WebSocket webSocket) {
Log.e(TAG, "webSocket is null");
Log.e(TAG, "Metodo onCompleted");
if (ex != null) {
Log.e(TAG, ex.getMessage(), ex);
return;
}
//Log.e(TAG, "webSocket.isOpen(): " + webSocket.isOpen());
webSocket.send("a string");
webSocket.send(new byte[10]);
webSocket.setStringCallback(new WebSocket.StringCallback() {
public void onStringAvailable(String s) {
System.out.println("I got a string: " + s);
Log.e(TAG, "I got a string: " + s);
//showToast("I got a string: " + s);
}
});
webSocket.setDataCallback(new DataCallback() {
#Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList byteBufferList) {
System.out.println("I got some bytes!");
Log.e(TAG, "I got some bytes!");
// note that this data has been read
byteBufferList.recycle();
}
});
}
});
}
My Server code:
private void conectar() {
AsyncHttpServer server = new AsyncHttpServer();
server.listen(PORTA);
server.get("/", new HttpServerRequestCallback() {
#Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
response.send("Hello!!!");
}
});
server.websocket("/", new AsyncHttpServer.WebSocketRequestCallback() {
#Override
public void onConnected(final WebSocket webSocket, AsyncHttpServerRequest request) {
Log.e(TAG, "Metodo: onConnected");
_sockets.add(webSocket);
//Use this to clean up any references to your websocket
webSocket.setClosedCallback(new CompletedCallback() {
#Override
public void onCompleted(Exception ex) {
Log.e(TAG, "Metodo onCompleted from webSocket object");
try {
if (ex != null)
Log.e("WebSocket", "Error");
} finally {
_sockets.remove(webSocket);
}
}
});
webSocket.setStringCallback(new WebSocket.StringCallback() {
#Override
public void onStringAvailable(String s) {
Log.e(TAG, "Metodo onStringAvailable from webSocket object");
if ("Hello Server".equals(s))
webSocket.send("Welcome Client!");
}
});
}
});
Anyone knows tell me why Can't I connect my server?
I have tested the server code in another app websocket tester from google play.
The app server it's Ok.
However I cannot connect from my client app?
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();
I am working on websocket communication with Autobahn.
On the main.class of my app, I set to call 'connect()' when users click a button.
// Toggle Button event
tButton = (ToggleButton) findViewById(R.id.toggleButton1);
tButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
}else{
}
}
});
And after that, there is MyOffers.class, and if this class is accessed,
MyOffers_Fragment class is produced four times automatically, because MyOffers.class contains 'carousel view' and there are four products.
On 'MyOffers_Fragment' class, when users click one of the image of products, message should be sent.
if (pos == 0) {
product_photo.setImageResource(R.drawable.myoffers_0);
product_photo.setOnClickListener(new ImageButton.OnClickListener(){
public void onClick(View v){
String id = "Product0";
Log.d(TAG, "Current product is : " + id);
A.sendMessage(id);
}
});
}
But 'mConnection.sendTextMessage(id1);' this line makes 'NullPointerException' error.
There is a class 'Websocket_Connector.class'
public class WebSocket_Connector {
private static final String TAG = "ECHOCLIENT";
public final WebSocketConnection mConnection = new WebSocketConnection();
public void connect(final String wsuri) {
Log.d(TAG, "Connecting to: " + wsuri);
try {
mConnection.connect(wsuri, new WebSocketHandler() {
#Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri );
Log.d(TAG, "Connection successful!\n");
}
#Override
public void onTextMessage(String payload) {
Log.d(TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.d(TAG, "Connection closed.");
}
});
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
public void sendMessage(String message) {
connect("ws://192.168.x.xxx:xxxx");
mConnection.sendTextMessage(message);
}
}
I called 'connect()' in the main page class, and after that try to send message.
But, it's not working..Can you please help me out?
public class WebSocket_Connector {
private static final String TAG = "ECHOCLIENT";
public final WebSocketConnection mConnection = new WebSocketConnection();
private String tmpString = "";
public void connect(final String wsuri) {
Log.d(TAG, "Connecting to: " + wsuri);
try {
mConnection.connect(wsuri, new WebSocketHandler() {
#Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri );
Log.d(TAG, "Connection successful!\n");
mConnection.sendTextMessage(tmpString);
tmpString = "";
}
#Override
public void onTextMessage(String payload) {
Log.d(TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.d(TAG, "Connection closed.");
}
});
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
public void sendMessage(String message) {
if (mConnection.isConnected())
mConnection.sendTextMessage(message);
else {
tmpString = message;
connect("ws://192.168.x.xxx:xxxx");
}
}
}