Android - Autobahn web socket communication - android

I am working on Web socket communication with Autobahn library.
The problem I have is after connecting server, then message should be sent without connection again. But the message is sent with different connection that it connects to server every single time to send a message.
public class WebSocket_Connector extends Activity{
private static final String TAG = "ECHOCLIENT";
private static final String TAG1 = "My app";
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()) {
Log.d(TAG1, "Messeage is sent : " + message);
mConnection.sendTextMessage(message);
}
else {
tmpString = message;
connect("ws://192.168.3.100:7681");
}
}
}
This is the code I have, and...When you see "sendMessage" method, it always goes to 'else' not, if loop. Any suggestion 'experts' please..?

i don't know the package name you are dealing with for websocket. So first it has to be provided to get reliable answer to your question. But let say if it is something similar to :
https://code.google.com/p/weberknecht/source/browse/trunk/src/main/de/roderick/weberknecht/WebSocketConnection.java?r=2
note: i have not seen there isConnected() method but assume that it is added somewhere else.
you can see from source that onOpen() (line 88) is called before connected = true; on line (91). if this member var will be used as result of isConnected() then your code always will follow "else" part of the condition.
i would advice to dig into websocket api and its usage pattern further.

Related

How to implement connection failover in client side

I am trying to implement connection failover in android application. Basically I have list of URLs which application connect using websocket, In case of unable to connect with any url I need to try a second connection. API which I am using to connect with websocket in android side is not synchronous. so when I start connect to websocket after executing this method I dont know either connection establish or not until OnOpen method called and then I set some boolean there to use further.
What I tried: One solution in my mind is to start to call connect method from a thread and sleep this for certain time if OnOpen method called within timespan is ok otherwise try to use second connection url.
Can someone give me hint how I can resolve this. Here is a sample code (without thread implementation):
private DataUploader() {
// test list of url
urlList = new ArrayList<String>();
urlList.add("192.168.220.197:9001/observation/");
urlList.add("192.168.220.197:9002/observation/");
urlList.add("echo.websocket.org");
connectWebSocket();
}
public void connectWebSocket() {
if (urlList.size() > -1) {
String url = urlList.get(index);
this.connect(url);
index++;
}
}
private void connect(String websocketEndPointUrl) {
URI uri;
try {
websocketEndPointUrl = "ws://" + websocketEndPointUrl;
uri = new URI(websocketEndPointUrl);
} catch (URISyntaxException e) {
e.printStackTrace();
return;
}
mWebSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("Websocket", "Opened");
isReady = true;
}
#Override
public void onMessage(String s) {
///
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed " + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error " + e.getMessage());
}
};
mWebSocketClient.connect();
}

Slack Real-Time-Messaging websocket

Trying to implement this in application. Slack RTM
After call to rtm.start I get JSON-response and extract wss url. After it, following documentation I need to open websocket.
Tried two libraries
compile 'com.koushikdutta.async:androidasync:2.+'
compile 'org.java-websocket:Java-WebSocket:1.3.0'
First gives TimeoutException, second - enters onClose method with i = -1, b = true (onError or onOpen are not called, see code below).
connection = (HttpURLConnection) new URL(getQuery(URL + "rtm.start",
new Pair<>("token", TOKEN))).openConnection();
final String response = readIs(connection.getInputStream());
JSONObject jResponse = new JSONObject(response);
String uri = (String) jResponse.get("url");
With Java-WebSocket I've tried this code (standard from example on github):
connectWebSocket(uri);
private void connectWebSocket(String uriStr) {
URI uri;
try {
uri = new URI(uriStr);
} catch (URISyntaxException e) {
e.printStackTrace();
return;
}
log(uri.toString());
log(uri.toASCIIString());
mWebSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen(ServerHandshake serverHandshake) {
log("Opened");
mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL);
}
#Override
public void onMessage(String s) {
log(s);
}
#Override
public void onClose(int i, String s, boolean b) {
log("Closed " + s + " " + b + " number: " + i);
}
#Override
public void onError(Exception e) {
log("Error " + e.getMessage());
}
};
mWebSocketClient.connect();
}
As I've said above - only onClose is called.
With AndroidAsync tried standard code from example too:
AsyncHttpClient.getDefaultInstance().websocket(uri, "wss", (ex, webSocket) -> {
if (ex != null) {
log(ex.getMessage());
return;
}
webSocket.send("a string");
});
I've never worked with websockets on android before, and can't understand what am I doing wrong. Will appreciate your help.
Url in JSON is of type of
wss://ms156.slack-msgs.com/websocket/LYBUMUtG-bqj9HkKwEB5Yk_DCyPeRbnZ4viUJYHzrzJnLr-M74d46IQ9khTF8rik-v6ckJ4hqXPRi666hyPR6pismYBZBsggJUade3LOARc=
Finally my coleague managed to open this socket using OkHttp. If somebody is interested - code of test project is provided below:
http://pastebin.com/3YhLjAn7
What is interesting - in the end we decided not to use RTM, because load for one connection is too high - you receive events from all chats and there is no way to set filter only for one specific.

How to enable the XEP-0199 in Smack?

I'm using aSmack. My app listens a chatroom and reacts to the messages but it never send a message. The app doesn't receive more messages if the chatroom remains in silence for a while and then a new message is sent. I researched and I think that XEP-0199 is the solution here. I see that #Flow (the current Smack maintainer) implemented it and the issue related was closed.
I think that I need to use PingProvider but I really don't know how to connect this class with the Connection.
How can I enable the XEP-0199? How can I use PingProvider?
Connection code:
smack = SmackAndroid.init(getActivity().getApplicationContext());
connection = new XMPPConnection(App.getServer());
connection.addConnectionListener(new ConnectionListener() {
private final static String SMACK = "SMACK";
#Override
public void reconnectionSuccessful() {
Log.i(SMACK , "reconnectionSuccessful");
}
#Override
public void reconnectionFailed(Exception e) {
Log.i(SMACK, "reconnectionFailed", e);
}
#Override
public void reconnectingIn(int seconds) {
Log.i(SMACK, "reconnectingIn " + seconds);
}
#Override
public void connectionClosedOnError(Exception e) {
Log.i(SMACK, "connectionClosedOnError", e);
}
#Override
public void connectionClosed() {
Log.i(SMACK, "connectionClosed");
}
});
connection.connect();
connection.login(user, password);
I fix the problem implementing the ping response manually:
connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
connection.sendPacket(new Pong((Ping) packet));
}
}, new PacketFilter() {
#Override
public boolean accept(Packet packet) {
return packet instanceof Ping;
}
});
To prevent user from disconnecting your session
PingManager pm = PingManager.getInstanceFor(MyApplication.connection) ;
pm.setPingInterval(5) ; // 5 sec
pm.pingMyServer() ;
pm.registerPingFailedListener(new PingFailedListener() {
#Override
public void pingFailed() {
Log.e(TAG , "pingFailed") ;
}
});
XEP 0199 is not a solution, Ping is used to check weather the server is up or not. actually you will send ping to the server.
Now as fas as your problem is concerned. Show me the message stanza that you are trying to send. and also check if the chat-room is public or private. you can not send a message to a private chat room.
Answer Updated:
Try using this code for detecting message recieve
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
Network.connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Message message = (Message) packet;
if (message.getBody() != null) {
String fromName = StringUtils.parseBareAddress(message.getFrom());
Log.i("XMPPClient", "Got text [" + message.getBody() + "] from [" + fromName + "]");
//recieve.setText(message.getBody());
/*messages.add(fromName + ":");
messages.add(message.getBody());*/
// Add the incoming message to the list view
item = new RowItem(R.drawable.billing, message.getBody());
adapter = new CustomListViewAdapter(getBaseContext(),
R.layout.list_item, rowItems);
rowItems.add(item);
//listView.setAdapter(adapter);
}
}
}, filter);
I called PingManager.getInstanceFor method to enable XEP-0199 support.

AsyncTask in an android socket application

i am making an android socket app to communicate with the server for creating accounts, and i noticed i have to do this in AsyncTask sub class, even when i seperate it to another class without UI,but i am terribly confused how can i use AsyncTask on this, is there any one expert here who can help me please?
this is the code:
public class AccountCreator extends Activity {
public AccountCreator(){
super();
}
// for I/O
ObjectInputStream sInput; // to read from the socket
ObjectOutputStream sOutput; // to write on the socket
Socket socket;
public static String LOGTAG="Lifemate";
public String server = "localhost";
public String username = "user";
public String password = "rezapassword" ;
public int port = 1400;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(LOGTAG,"oncreate called");
this.start();
}
AccountCreator(String server, int port, String username,String password) {
this.server = "localhost";
this.port = 1400;
this.username = username;
Log.i(LOGTAG,"first accountcreator called");
}
public boolean start() {
// try to connect to the server
//this method returns a value of true or false when called
try {
socket = new Socket(server, port);
}
// if it failed not much I can so
catch(Exception ec) {
// display("Error connectiong to server:" + ec);
Log.i(LOGTAG,"Error connectiong to server:" + ec);
return false;
}
String msg = "Connection accepted " + socket.getInetAddress() + ":" +
socket.getPort();
// display(msg);
Log.i(LOGTAG, msg);
/* Creating both Data Stream */
try
{
sInput = new ObjectInputStream(socket.getInputStream());
sOutput = new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException eIO) {
// display("Exception creating new Input/output Streams: " + eIO);
Log.i(LOGTAG,"Exception creating new Input/output Streams: " +
eIO);
return false;
}
// creates the Thread to listen from the server
// Send our username to the server this is the only message that we
// will send as a String. All other messages will be ChatMessage objects
try
{
sOutput.writeObject(username);
sOutput.writeObject(password);
}
catch (IOException eIO) {
// display("Exception doing login : " + eIO);
Log.i(LOGTAG,"Exception doing login : " + eIO);
disconnect();
return false;
}
// success we inform the caller that it worked
return true;
}
// private void display(String msg) {
// TextView screenprint = (TextView)findViewById(R.id.systemmessages);
// screenprint.setText(msg);
// }
private void disconnect() {
Log.i(LOGTAG,"reached disconnect");
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {} // not much else I can do
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {} // not much else I can do
try{
if(socket != null) socket.close();
}
catch(Exception e) {} // not much else I can do
}
public void Begin() {
Log.i(LOGTAG,"it begun");
int portNumber = 1400;
String serverAddress = server;
String userName = username;
String newpassword = password;
AccountCreator accountcreator = new AccountCreator(serverAddress, portNumber,
userName,password);
if(!accountcreator.start())
return;
}
}
i was trying to put whole code in Async, i dont know if was i right, do i need to do that also or just some parts of it?
In brief, AsyncTask contains a few methods which may be helpful:
onPreExecute:
This method is the first block of code executed when calling asyncTask.execute(); (runs on mainUIThread).
doInBackground:
Here you put all the code which may suspend you main UI (causes hang for your application) like internet requests, or any processing which may take a lot of memory and processing. (runs on background thread), contains one parameter taken from the asyncTask.execute(ParameterType parameter);
onPostExecute
Runs after doInBackground(). Its parameter is the return value of the doInBackground function, and mainly you put the changes in UI need to be done after the connection is finished (runs on mainUIThread)
You have to declare another class within the class you have already created.
class SomeName extends Async<Void, String, Void>{
protected void OnPreExecute(){
// starts the task runs on main UI thread
// Can be used to start a progress dialog to show the user progress
}
#Override
protected Void doInBackground(Void... params){
// does what you want it to do in the background
// Connected to the server to check a log-in
return result;
}
protected void OnPostExecute(Void result){
// finishes the task and can provide information back on the main UI thread
// this would be were you would dismiss the progress dialog
}
}

android - Autobahn Websocket Connection

I am working on Autobahn Web socket communication. There is a carousel view in my application, and there are four images. When users click on of the images, then connects to server with websocket and send message. But the problem is that when I select the images, it connects to server correctly, but client(android device) connects to the websocket every single time when the message is sent.
Here is my code..
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);
}
});
}
Websocket.class
public class WebSocket_Connector extends Activity{
private static final String TAG = "ECHOCLIENT";
private static final String TAG1 = "My app";
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()) {
Log.d(TAG1, "Messeage is sent : " + message);
mConnection.sendTextMessage(message);
}
else {
tmpString = message;
connect("ws://xxx.xxx.x.xxx:xxxx");
}
}
}
It doens't go to 'if (mConnection.isConnected())' here..always goes to else.

Categories

Resources