1

I have a backend written with express and an app with Java for android.

Background:

I want to create socket communication between the app and the server, but I can't connect to the server from the app.

The backend side is fully tested, and I can send requests from postman and receive data as well. This is the code inside the server that handles the socket:

import { Server } from "socket.io";
import { SOCKET_EVENTS } from "../../constants/socket.js";
import { getBlockchainBlock } from "../crypto/crypto.js";

const io = new Server(4000, {
  cors: {
    origin: "*",
  },
});

export const openSocket = () => {
  io.on(SOCKET_EVENTS.CONNECTION, async (socket) => {
    console.log("user connected! socket id:", socket.id);

    io.emit(SOCKET_EVENTS.NEW_TASK, {
      data: await getBlockchainBlock(),
    });

    socket.on(SOCKET_EVENTS.TASK_FINISHED, (data) => {
      console.log("User task is done with data:", data);
    });

    socket.on(SOCKET_EVENTS.DISCONNECT, () => {
      console.log("user disconnected! socket id:", socket.id);
    });
  });
};


Android side

I added the socket.io-client library to the android app:

    implementation ('io.socket:socket.io-client:2.0.0') {
        exclude group: 'org.json', module: 'json'
    }

My attempt to add the socket library in order to communicate with the server:

public class MainActivity extends AppCompatActivity {

    Socket mSocket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.test);
        textView.setText("Some test");

        Emitter.Listener onNewTask = new Emitter.Listener() {
            @Override
            public void call(final Object... args) {
            }
        };
        Emitter.Listener taskFinished = new Emitter.Listener() {
            @Override
            public void call(final Object... args) {
                mSocket.emit("taskFinished", "Task is finished");
            }
        };

        try {
            mSocket = IO.socket("http://ipAddress:4000");
            mSocket.on("newTask", onNewTask);
            mSocket.on("connection", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    System.out.println("Connected to server!");
                }
            });
            mSocket.on("taskFinished", taskFinished);
            mSocket.connect();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

    }
}

The problem:

I cant see the Connected to server! print, when I used a debugger to debug the app the mSocket.connect(); line was called but there was never a connection. In addition - I can see in the backend prints for new connection when trying it via postman, but nothing shows when running the android code (seems like there is no connection)

Getting the IP address

The server is sitting on http://localhost:4000, according to this thread I needed to replace localhost with the IP address.

To do so I opened up cmd and run the ipconfig command and replaced localhost with IPv4 Address

Extra info

Those are the constants names I am using inside the server:

export const SOCKET_EVENTS = {
  CONNECTION: "connection",
  NEW_TASK: "newTask",
  TASK_FINISHED: "taskFinished",
  DISCONNECT: "disconnect",
};
Tamir Abutbul
  • 7,301
  • 7
  • 25
  • 53
  • For http protocol on Android 11+ you need to enable clearTextTraffic in application tag of manifest file. – blackapps Apr 18 '23 at 16:48
  • And you use an Android device? Not an emulator? – blackapps Apr 18 '23 at 16:49
  • @blackapps I used both android device and emulator. After adding `android:usesCleartextTraffic="true"` line I could see the `user connected! socket id` print on the server. But I could not emit event to the server on connection (I have replaced `System.out.println("Connected to server!");` with `mSocket.emit("taskFinished", "message");` ) – Tamir Abutbul Apr 19 '23 at 21:13
  • 1
    You should not replace that line. Only add a new one. – blackapps Apr 20 '23 at 09:14
  • Couldnt you emit() or was the message not received? – blackapps Apr 20 '23 at 09:15
  • If you used both device and emulator then used ip's should be different. What are you doing? – blackapps Apr 20 '23 at 09:16
  • The message is not received on the backend side, I could send it from the android device. I have tried running the client side both on Android and emulator. – Tamir Abutbul Apr 20 '23 at 09:36
  • Dont repeat yourself if asked which ip's you used then. Give info. Show what you do. – blackapps Apr 20 '23 at 09:44
  • I run ipconfig on the cmd, and used the ipv4. Does that answer your question ? – Tamir Abutbul Apr 20 '23 at 09:45
  • No. For several reasons. one of them is and i repeat: `If you used both device and emulator then used ip's should be different.`. – blackapps Apr 20 '23 at 10:48
  • And why is that? that IP is the server IP, and the server running locally on the same network, not the device. Shouldn't it be the same? – Tamir Abutbul Apr 20 '23 at 10:49
  • `the server running locally on the same network, not the device.` ???? And where is your emulator running? We have no idea about your setup. On which pc is the server running? – blackapps Apr 20 '23 at 10:53
  • Both The server and the Android device are running locally on the same network. In order to communicate between the emulator/real device to the server using sockets I needed the address of the server - hence the IP v4 address. Does this make things clear? – Tamir Abutbul Apr 20 '23 at 11:10
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/253256/discussion-between-tamir-abutbul-and-blackapps). – Tamir Abutbul Apr 20 '23 at 11:14

2 Answers2

0

Can you try to catch all Exception so that any exception would got caught and show the stack trace and error message? It appears to me that you are trying to establish TCP socket, so the URL should be tcp://

Tamir Abutbul
  • 7,301
  • 7
  • 25
  • 53
ttng_
  • 17
  • 5
  • I have changed my code into catching every exception and tried the tcp:// but it didn't solve the issue – Tamir Abutbul Apr 18 '23 at 16:30
  • Did you try to connect to the server with the new URL in Postman? You can also try to open the emulator's browser and enter the URL to see if it receives response or not, as well. I shouldn't be asking you to show the IPs that you have, so, you can try to do an ipconfig and try out all the IPs that seems to be reasonable. – ttng_ Apr 18 '23 at 16:33
  • Yes, using postman everything is working with the new URL. Trying to write the URL to the browser failed (because no SSL over http) – Tamir Abutbul Apr 19 '23 at 21:11
0

The solution was to add android:usesCleartextTraffic="true" under the application tag in the manifest

Tamir Abutbul
  • 7,301
  • 7
  • 25
  • 53