I'm using autobahn android web socket library to build my web socket client application.
In order to keep the web socket connection alive for a long time, I need to periodically send ping messages from the client.
How can I do that with auotbahn android web socket library?
AutobahnAndroid's WebSocketWriter supports client pong messages, and AutobahnPython claims the following:
explicit processing of Pings/Pongs is unnecessary normally - AutobahnPython will do the right thing under the hood.
However, during execution of a simple chat client-server setup, I observe no such ping/pong heartbeat messages.
From what I have read, it is unclear from both the documentation and the source, what the full requirements are for enabling implicit Autobahn* heartbeats.
My personal solution involves issuing a ping from the server during onConnection and the appropriate onMesssage, and something similar to the following client code onMessage:
if (payload.equals("ping from the server"))) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
myWebSocket.sendTextMessage("pong from the client");
}
}, 1000L);
}
... which schedules a pong response to be sent by the client, 1 second after receiving a ping from the server.
You can use the pull request that I just submitted
https://github.com/tavendo/AutobahnAndroid/pull/67
which adds sendPingMessage(byte[] payload) and onPongMessage(byte[] payl).
Related
I am a newbie to RXKotlin/RXJava.
I am developing the background service in Android.
In my service, I have
Bluetooth socket
TCP Socket
Whenever the data is available on the Bluetooth socket, read and write to the TCP socket. And whenever data is received in the TCP socket, write to the Bluetooth socket.
Can someone help me:
how to achieve this using Observables?
how to exchange the socket id information?
how to exchange the data?
Thanks
Please try using RxSubjects (https://blog.mindorks.com/understanding-rxjava-subject-publish-replay-behavior-and-async-subject-224d663d452f)
Let me take PublishSubject as an example here.
//a publish subject which publishes int values
public PublishSubject<Integer> source = PublishSubject.create();
source.onNext(1);
source.onNext(2);
So above lines of code goes in Bluetooth socket class.
Now in TCP socket class, using the source, you can observe here.
source
.subscribe(
{
//result
},
{
//error
}
)
Thats it.
Please make sure, the subscription happens before Bluetooth socket starts publishing data.
I am creating an android chat application using a smack open fire. The problem that I am facing is I know how to send and accept subscription requests but how can I know if I have received any subscription request.
I have used Stanza listener but the listener is only listening to incoming chat messages, not subscription requests.
Below is my code
StanzaFilter filter=new StanzaTypeFilter(Message.class);
PacketCollector collector=connection.createPacketCollector(filter);
connection.addAsyncStanzaListener(new StanzaListener() {
#Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
Log.wtf("MA","Stanz listner");
}
},filter);
I am a beginner in smack, please help me how can I listen for incoming subscription request. Thanks in advance.
A subscription request is not a Message. It is a Presence instead.
So, you probably should try:
StanzaFilter filter = new StanzaTypeFilter(Presence.class);
Reference: RFC 3921 - Section 6 - Managing Subscriptions
This is how I have done in my android code
StanzaFilter subscribefilter = PresenceTypeFilter.SUBSCRIBE;
PresenceSubscribeListener subscribeListener = new PresenceSubscribeListener(context.getApplicationContext(), connection);
connection.addSyncStanzaListener(subscribeListener, subscribefilter);
And then this connection object has been referenced in a long running service in Android. This has been done such that when a packet is received when you app is in background, you can still process the incoming presence packet.
P.S. I am using smack 4.1.9 in my android code.
I am using Android Autobahn client for communication with a web socket server. I need to know how the client detects tcp connection loss. Does it send TCP heart probes to detect this?
PS: error code : de.tavendo.autobahn.WebSocket.ConnectionHandler.CLOSE_CONNECTION_LOST
According to the source code, the CLOSE_CONNECTION_LOST error code is emitted when the endpoint calls close with an abnormal close code:
final int tavendoCloseCode = (close.mCode == 1000) ? ConnectionHandler.CLOSE_NORMAL : ConnectionHandler.CLOSE_CONNECTION_LOST;
I don't know exactly how your router is implemented, but in the source code, you have also a Ping / Pong implementation.
So you can expect that the connection loss is detected by sending some Ping / Pong WebSocket.
In my chat application, when I am sending messages/chats to the sender , I am checking the internet connection and the XMPP connection. If both are available, then only I allow the user to send the chat messages.
E.g -
if(connection.IsConnected){
//code to send the message to the sender
}
I am using Openfire Server.
I want to implement a functionality that when the internet is not available and when the user wants to send the message, it should send (i.e the messages should be added in the queue) and should send to the receipient as soon as internet is available again , just as Whats App.
Thanks
Your server is irrelevant in this case if you have no internet/XMPP connection. You just want to buffer the messages in your client and send them once your connection is reestablished.
I will assume you are using Smack or asmack, which means you will want to simply create a connection listener on your connection so that you can send buffered messages when the connection connection is reestablished.
connection.addConnectionListener(new ConnectionListener()
{
:
public void reconnectionSuccessful()
{
resendFromBuffer();
}
});
I'm currently working on a Project in my University which is an Android-App which is supposed to deliver data to a Server.
In order to do that I require a more or less consistent connection to the server via XMPP. It is not really important that the connection is there 100% of the time, but it because the system is supposed to be more or less invisible to the user, user-interaction is supposed to be minimal.
Both the server and the client are xmpp-clients. I use jabber.org as the xmpp server.
I have an Android-Service that is establishing the connection to server and delivers data and this works fine.
Now I tried to make the Service reconnect when connection is lost or is Changed from Wifi to GSM. I wanted to try to make this work with a broadcastreceiver listening to NETWORK_STATE_CHANGED_ACTION. But I did not even get this far.
This is the problem: I tried running the app and then just disabling my wifi. My Phone than automatically switches to GSM and I lose my connection (which I anticipated). But when I try to reconnect manually (e.g. restarting the service) I get errors from the Server. Also my status is still "available". From that moment on it takes way too long until I can connect again.
06-29 18:12:14.888: WARN/System.err(14246): resource-constraint(500)
06-29 18:12:14.890: WARN/System.err(14246): at org.jivesoftware.smack.NonSASLAuthentication.authenticate(NonSASLAuthentication.java:110)
06-29 18:12:14.890: WARN/System.err(14246): at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:404)
06-29 18:12:14.890: WARN/System.err(14246): at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
....
I am actually connected to the xmpp Server but it does not deliver my message:
06-29 18:12:14.882: INFO/System.out(14246): 06:12:14 nachm. RCV (1079704816): <iq type='error' id='7rhk4-70'><error code='500' type='wait'><resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>
Sometimes I don't get the error, but still no messages are being delivered.
So I think that the server is not allowing me to connect, because I did not disconnect before trying to reconnect. Which I find strange because I thought you could even connect from multiple clients to one account.
I'm posting some code that I think might be relevant:
public void connectToServer() throws XMPPException {
ConnectionConfiguration config = new ConnectionConfiguration(
serverADD, port,
service);
connection = new XMPPConnection(config);
connection.connect();
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
connection.login(user_JID,password);
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("available");
presence.setPriority(24);
presence.setMode(Presence.Mode.available);
connection.sendPacket(presence);
}
this is how I send the messages:
public void sendMessage(String message, String recipient) throws XMPPException {
chat = connection.getChatManager().createChat(recipient, this);
chat.sendMessage(message);
}
Does anyone hava an idea how to solve this? I would even use "dirty" tricks as long as my message gets delivered to the server.
By the way: The senders and the recipients jids are always the same (after initial setup). Just in case anyone thinks that could matter.
Deadlock during Smack disconnect
As Airsource Ltd. mentioned in his comment: Smack is suffering from an deadlock in disconnect() which is loged as SMACK-278. I have made a commit that fixes this in my smack fork.
Android reconnection handling
For the network fallover, have a look at the GTalkSMS receiver. It will issue a ACTION_NETWORK_CHANGED intent, with the boolean extras "available" and "fallover". Your service should "stop" the connection when "available=false" and "fallover=false". How you "stop" the connection is up to you. Sometimes the disconnect() takes very long even with the fix for SMACK-278, this is why we do the disconnect in an thread that will abort after x seconds and then creates a new Connection instance. We reconnect then when the intent with "available=true" is received.
You will find other examples in the GTalkSMS source. I have the app permanently running and it achieves a stable, but not 100% available connection (because of WLAN <-> GSM switches).