JavaPhoenixChannels
JavaPhoenixChannels copied to clipboard
Socket closes after every Channel.push command
The Server I connect to generates random URLs and once connected I need to join a channel and then maintain the connection. The server uses Phoenix protocol as well which is why I am using this library.
However whenever I do my initiate channel join command and get a return on my callback function, the library closes the socket. I am not able to find a way to keep the socket open long enough to make my any other calls.
Is there a way to prevent the socket from closing after I make the first push/join on the channel?
Hi, is it possible to show a code example? Also, are there any relevant logs? It's definitely possible it is a bug.
public class WebSocketConnection {
private WebSocketConnection(){
}
public static WebSocketConnection connection;
public static synchronized WebSocketConnection getInstance(){
if (connection == null)
{
connection = new WebSocketConnection();
}
return connection;
}
private static Socket socket;
private Channel channel;
public void connectWebSocket(String uri) {
try {
if(socket ==null || !socket.isConnected()) {
socket = new Socket(uri, 20000);
socket.reconectOnFailure(false);
socket.connect();
}
}
catch(Exception e)
{
}
}
public void join() throws IOException {
new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
channel = socket.chan("user", node);
try {
channel.join()
.receive("ignore", new IMessageCallback() {
@Override
public void onMessage(Envelope envelope) {
System.out.println("IGNORE");
}
}
)
.receive("ok", new IMessageCallback() {
@Override
public void onMessage(Envelope envelope) {
System.out.println("JOINED with " + envelope.toString());
ObjectNode node = new ObjectNode(JsonNodeFactory.instance)
//removed data from the values
.put("name", "")
.put("card", "")
.put("month","")
.put("year","")
.put("cvc","")
.put("address_line1", "")
.put("address_line2","")
.put("city","")
.put("state","")
.put("postal_code","")
.put("country","")
.put("phone_number","");
sendMessage("user","add_card",node);
}
}
);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
socket.onClose(new ISocketCloseCallback() {
@Override
public void onClose() {
System.out.println("Socket just closed");
}
});
}
public void sendMessage(final String topic, final String event, final JsonNode payload){
new AsyncTask(){
@Override
protected Object doInBackground(Object[] objects) {
Envelope envelope = new Envelope(topic, event, payload, UUID.randomUUID().toString());
// ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
channel.on("new:msg", new IMessageCallback() {
@Override
public void onMessage(Envelope envelope) {
System.out.println("NEW MESSAGE: " + envelope.toString());
}
});
try{
socket.push(envelope);
// channel.push(event,payload)
// .receive("ok", new IMessageCallback() {
// @Override
// public void onMessage(final Envelope envelope) {
// System.out.println("NEW MESSAGE: " + envelope.toString());
// //addToList(message);
// }
// })
// .timeout(new ITimeoutCallback() {
// @Override
// public void onTimeout() {
// System.out.println("MESSAGE TIMED OUT");
// }
// });
//channel.push(event,payload);
} catch (IOException e) {
e.printStackTrace();
// showToast("Failed to send");
};
return null;
}
}.execute();
}
}
Thanks, I'm looking into it today to see if I can reproduce it and find a cause
@gupta11 I wasn't able to reproduce the issue I don't think. I updated the code example a little bit and maybe that had something to do with it here is my version of WebSocketConnection.java
(I used the phoenix chat example for testing so topics and event names changed in my example:
package com.basstype.androidphoenixchanneltester;
import android.os.AsyncTask;
import android.util.Log;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.phoenixframework.channels.Channel;
import org.phoenixframework.channels.Envelope;
import org.phoenixframework.channels.IMessageCallback;
import org.phoenixframework.channels.ISocketCloseCallback;
import org.phoenixframework.channels.ITimeoutCallback;
import org.phoenixframework.channels.Socket;
import java.io.IOException;
import java.util.UUID;
public class WebSocketConnection {
private WebSocketConnection() {
}
public static WebSocketConnection connection;
public static synchronized WebSocketConnection getInstance() {
if (connection == null) {
connection = new WebSocketConnection();
}
return connection;
}
private static Socket socket;
private Channel channel;
public void connectWebSocket(String uri) {
try {
if (socket == null || !socket.isConnected()) {
socket = new Socket(uri, 20000);
socket.reconectOnFailure(false);
socket.connect();
ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
channel = socket.chan("rooms:lobby", node);
}
} catch (Exception e) {
}
}
public void join() throws IOException {
new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
try {
channel.join()
.receive("ignore", new IMessageCallback() {
@Override
public void onMessage(Envelope envelope) {
Log.d(WebSocketConnection.class.getName(), "IGNORE");
System.out.println("IGNORE");
}
}
)
.receive("ok", new IMessageCallback() {
@Override
public void onMessage(Envelope envelope) {
Log.d(WebSocketConnection.class.getName(), "JOINED with " + envelope.toString());
System.out.println("JOINED with " + envelope.toString());
ObjectNode node = new ObjectNode(JsonNodeFactory.instance)
//removed data from the values
.put("name", "")
.put("card", "")
.put("month", "")
.put("year", "")
.put("cvc", "")
.put("address_line1", "")
.put("address_line2", "")
.put("city", "")
.put("state", "")
.put("postal_code", "")
.put("country", "")
.put("phone_number", "");
sendMessage("new:msg", "new:msg", node);
}
}
);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
socket.onClose(new ISocketCloseCallback() {
@Override
public void onClose() {
Log.d(WebSocketConnection.class.getName(), "Socket just closed");
System.out.println("Socket just closed");
}
});
}
public void sendMessage(final String topic, final String event, final JsonNode payload) {
new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
Envelope envelope = new Envelope(topic, event, payload, UUID.randomUUID().toString());
ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
channel.on("new:msg", new IMessageCallback() {
@Override
public void onMessage(Envelope envelope) {
Log.d(WebSocketConnection.class.getName(), "NEW MESSAGE: " + envelope.toString());
System.out.println("NEW MESSAGE: " + envelope.toString());
}
});
try {
socket.push(envelope);
//channel.push(event,payload)
// .receive("ok", new IMessageCallback() {
// @Override
// public void onMessage(final Envelope envelope) {
// Log.d(WebSocketConnection.class.getName(), "NEW MESSAGE: " + envelope.toString());
// System.out.println("NEW MESSAGE: " + envelope.toString());
//addToList(message);
// }
// })
// .timeout(new ITimeoutCallback() {
// @Override
// public void onTimeout() {
// Log.d(WebSocketConnection.class.getName(), "MESSAGE TIMED OUT");
// System.out.println("MESSAGE TIMED OUT");
// }
// });
//channel.push(event,payload);
} catch (IOException e) {
e.printStackTrace();
// showToast("Failed to send");
}
;
return null;
}
}.execute();
}
}
Thank you so much for taking a look @bryanjos . I will check it next week and again check my code and revert back to you. I hope this works. :)
I'm having this same problem, as soon as I push a message.
The thing that is strange to me is that there doesn't seem to be adequate error reporting around the connection closing. If we can't find the bug for this, could we at least make sure there are mechanisms for appropriate error reporting to the Android logs?
I was not able to verify if this is working. I had a release that I was working towards and had to use another socket library with my own implementation of the phoenix protocol. @relwell can you post your code as well so that @bryanjos can check it out. I will try this in the new year once my release is done and see if the code works for me but for now it doesn't and closes the socket after the first message.
I managed to do some more debugging and I think I see the problem.
There's an error on the Elixir side, so I'm guessing the server is closing the channel. It seems like we should get something in the logs for this, shouldn't we?
Never mind. I'm able to confirm that even when pushing a well-formed message, using channel.push results in the channel trying to rejoin.
I have this problem too. And problem occurs in API 26, and in API 22 it's correct.
Is there a way anyone could show small example projects both on the Elixir and Android side with the issue present? I haven't been able to reproduce it on my own
I was also experiencing this but realized that I was updating the UI after I received a response from the push on a background thread (the thread the socket was using). Running the block of code in the response callback on the main thread will no longer cause the socket to be disconnected.