Socket.io connection doesn't work for multiple fragments - java

I am creating a project with socket.io. It works really fine as long as there is just one fragment. However as I add more fragments in main activity, it starts creating multiple connections, which i think is not a good idea.
At first I connected to socket.io directly from fragments but that was creating one connection for each fragment. So I created a connection in Application class and used that in fragments which instantly solved multiple connection problem. But now a new problem has occurred.
In case of internet disconnection and reconnection, fragment doesn't get reestablished connection from Application class. I have been trying for over a week but no solution. strange thing is, i searched on internet and stackoverflow but not a single such question is ever asked.
here is connection code in Application class
synchronized public Socket getSocket() {
if (mSocket == null) {
try {
IO.Options opts = new IO.Options();
opts.reconnection = true;
opts.reconnectionDelay = 1000;
mSocket = IO.socket("http://ddbharti.in", opts);
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "EVENT_CONNECT");
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "EVENT_DISCONNECT");
}
}).on(Socket.EVENT_ERROR, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d(TAG, "error");
}
});
mSocket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return mSocket;
}
and this is how each fragment is connecting
socket = application.getSocket();
socket.emit("tag", tag);
If internet is working fine, this setup works flawlessly, loads in 300 milliseconds. However as i disconnect/reconnect internet or I keep internet disconnected and start the app and then connect to internet. Connection in Application class connects quickly, but due to some reason connection in current fragment just doesn't get it.
If i switch fragments then it starts listening to connection from Application class again.
So am i missing something here? How can i force fragment to get connection from application class again in case of reconnection without reloading whole fragment?
Any help is greatly appreciated.

So i created an event listner to listen to socket connection status and show ui accordingly. Just one connect with event listner was all that was needed.

Related

Can't connect to local socketIO nodejs server on android

I have made a basic nodejs server that console logs when a user connects to the server. i am using socket io for this because i wanna make a chat application. On my android side im trying to create a connection to this local server but i never get the console log when i try and socket.connected stays on false. also never get a error or something when trying to connect
I have tried some examples from the internet. i got 1 example working deleted everything that i didnt use and it still works. i copy paste from that example to my own project and still didn't work.
This is the example i used.
Here is the code of my project
Node JS:
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Android:
public class MainActivity extends Activity {
private Socket socket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ChatApplication app = (ChatApplication) getApplication();
socket = app.getSocket();
socket.connect();
}
}
ChatApplication class:
public class ChatApplication extends Application {
private Socket mSocket;
{
try {
mSocket = IO.socket("http://192.168.0.109:3000");
} catch (Exception e) {
Log.e("Error", e.toString());
}
}
public Socket getSocket() {
return mSocket;
}
}
Android Studio emulator usually prevents localhost connections, I'm not sure if this happened in your case, but it has happened to me. Try popping out your Logcat in Android Studio and see if you can find something that indicates that the localhost connection got denied.
Not sure if this is it, but you should check.

Internet Connection Check behaving weirdly

I've been needing a way to check if the user has Internet. I used this approach:
public class InternetCheck extends AsyncTask<Void, Void, Boolean> {
private Consumer mConsumer;
public interface Consumer {
void accept(Boolean internet);
}
public InternetCheck(Consumer consumer) {
mConsumer = consumer;
execute();
}
#Override
protected Boolean doInBackground(Void... voids) {
try {
Socket sock = new Socket();
sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
sock.close();
Log.w("INTERNET CHECK", "has Internet");
return true;
} catch (IOException e) {
Log.w("INTERNET CHECK", "NO Internet");
return false;
}
}
#Override
protected void onPostExecute(Boolean internet) {
mConsumer.accept(internet);
}
}
... the following way:
new InternetCheck(hasInternet -> { /* do something with boolean response */ });
However, it seems like it isn't as robust as one would think: sometimes (not so often) my phone is connected to WiFi and yet this method returns false.
What are the possible scenarios/diagnostics as of why this behaviour might happen?
My personal experience is that it seems to happen when my phone has my application open and is connected to a WiFi. Then, the phone goes to sleep and I move places and open it back up to the application on a new WiFi connection. The check returns false despite my phone displaying that it clearly has established the new WiFi connection (since it was a saved network).
However, this is not the only way this method seems to have failed. Another developer had it happen while he didn't change his WiFi connection.
Wifi connections are disconnected when the phone goes to sleep. It takes time for the connection to be re-established when the phone wakes up again.
Your 1.5 second connection timeout is too short to accommodate that extra delay.
Also, the DNS server, or the intermediate network, may simply be busy. Again, the connection timeout is too short.
Before inventing your own way to check internet connectivity, you should read these:
Android Developer Guide: Determine and monitor the connectivity status
StackOverflow: Android check internet connection

Connecting for the first time - reconnect

Currently this is not supported in paho java library, but I need this functionality in our application. For example, on application startup, we didn't have network connection, but after 30 seconds or so, we established connection successfully so I want my client to connect automatically.
My question is - what would be best approach to accomplish this? What I tried so far is to try to reconnect if something goes wrong during connect method. And since we use RxJava I have scheduled execution of the same method which is responsible for client connection. It will be easier if I paste the code.
private void connect(String brokerUrl) {
try {
LOG.info("Connecting to the broker...");
mqttClient.connect(connectionOptions, "Connecting", new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
LOG.info("Successfully conected to the broker.");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
LOG.error("Failed to connect to broker. Trying to reconnect in {} milliseconds...", connectionRetryTimeout, exception);
// try to reconnect in few seconds
Schedulers.io().scheduleDirect(() -> connect(brokerUrl), connectionRetryTimeout, TimeUnit.MILLISECONDS);
}
});
} catch (MqttException e) {
LOG.error("Connection error.", e);
}
}
What happens like this is that, when network connection is available I manage to connect automatically, but second thread is created which continues to retry to connect to broker. Does anyone already implemented this, or do you have any other suggestions?
The best way would be implementing a callback (asynchronous event based) that informs you as soon as teh network is available again
interface INetworkCallback{
void onNetworkStateChange(boolean newState);
}
and somewhere implement the interface

How to make sure that my windows system is connected to network

I am creating a utility that also has a list of few ip addresses that are attached to my network.
I need to create a module that keeps refreshing that list so that only alive IP's are present in that list.
I have thought of achieving this by using PING on each of the IP's and remove non responsive ones.
Problem is that I dont want to delete IP's when my System itself is not connected to network as in that case all of the IP's will get deleted for obvious reasons.
How can I be sure that my system is connected to some network?
I am using Java.
I have tried looking over other questions but could not find anything relevant.
[EDIT1]
IP list is manually added set,and server has several more IP's which I dont need to care about.So I cant do a lookup in entire server as suggested by #Hoijf below. Also the IP's change consistently, thats why I need to keep my list updated so that we can replace non responsive servers/IP.
Problem is that I dont want to delete IP's when my System itself is
not connected to network as in that case all of the IP's will get
deleted for obvious reasons.
This is a typical network isolation problem. You should consider cases where your LAN is still up (ipconfig would show NIC's status as UP), but, you've lost internet connectivity (at some upstream router). As a solution, you could consider pinging a reference IP/host that is always supposed to be up.
So, you should create a policy in your program to ping this reference host to check if you should remove the host from your active list.
Scan the network and save the IPs which are active.
Store the IPs in an array and iterate over this array until the user chooses to stop or refresh (back to step 1).
Display the status of each IP.
public class temp
{
static ArrayList<InetAddress> history = new ArrayList<InetAddress>();
static Timer timer;
static InetAddress add;
public static void main(String[] args)
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int timeout = 25;
timer = new Timer(1000, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
for(InetAddress ii : history)
{
try
{
System.out.println(ii+" >> "+ii.isReachable(timeout));
} catch (IOException e1){System.out.println(ii+" >> Failed");}
}
}
});
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
while(true)
{
try
{
history.add(InetAddress.getByName(br.readLine()));
} catch (UnknownHostException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t.start();
timer.start();
}
}

Writing to an AsynchronousSocketChannel and processing the data in an Event-based way

I'm trying to figure out how to send data between sockets in Java (this is part of a bigger project and I'll get back and answer my previous two questions related to that once I can resolve this..). I would like to connect a client and a server socket asynchronously in Java, and then send messages between them, and get a callback, say, when I have sent a message from the client to the server.
I think I have managed to get the set-up working. Here is my code:
private AsynchronousServerSocketChannel socListener;
private AsycnchrnonousSocketChannel socClient;
//This is the GUI callback for the button that initiates the socket server
private void button_StartSocketServerActionPerformed(ava.awt.event.ActionEvent evt)
{
try{
InetAddress ipLocal= InetAddress.getLocalHost();
InetSocketAddress ipSocket=new InetSocketAddress(ipLocal,8221);
m_socListener= AsynchronousServerSocketChannel.open().bind(ipSocket);
m_socListener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>()
{
#Override
public void completed(AsynchronousSocketChannel ch, Void att)
{
// accept the next connection
m_socListener.accept(null, this);
// handle this connection
}
#Override
public void failed(Throwable exc, Void att) { }
}
);
}
catch (Exception e){
}
}
//This is the GUI callback for the button that initiates the client socket
private void button_StartClientSocketActionPerformed(java.awt.event.ActionEvent evt)
{
try
{
socClient=AsynchronousSocketChannel.open();
InetAddress ipLocal= InetAddress.getLocalHost();
InetSocketAddress ipSocket=new InetSocketAddress(ipLocal,8221);
socClient.connect(ipSocket, null, new CompletionHandler<Void,Void>()
{
#Override
public void completed(Void att1, Void att2)
{
// handle this connection
}
#Override
public void failed(Throwable exc, Void att) {}
}
);
}
catch (Exception e){
}
}
I'm including the server and the client in the same file for simplicity of testing.
So supposing the connection is successfully established, and I have a process on a timer (say) that was writing data to the server socket, I'd like to have the client socket 'listen' for this new data being sent from the server and then generate a callback when a write occurs (without doing something like periodically checking via a timer and a while loop to check that whether new data has been added). This is accomplishable in C# and a nice tutorial is available at:
http://www.developerfusion.com/article/3918/socket-programming-in-c-part-1/2/
Any tips on how to do this would be greatly appreciated. Thanks!
Chris
You could use RMI to accomplish that, the documentation can be found there:
http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136424.html
With this, your server could notify your client as much as you need.

Categories