1
votes

I am trying to get into IoT and want to make an app send a string from an android phone to a Linux pc. The app does this by implementing an asynctask:

//From the java docs, slightly modified
private Void sendThroughSocket(String s, String host, int port) {
    Log.d("E", "In send through  socket");
    final String hostName = host;//Host is the address of the receiver, can be IP or domain
    int portNumber = port;
    //Check if device is connected to internet

    try {
        Socket clientsocket = new Socket(hostName, portNumber); //one of 2-way point communication
        Log.d("E", "Created Socket: ");
        DataOutputStream DOS = new DataOutputStream(clientsocket.getOutputStream());
        if (clientsocket.isConnected())
            Log.d("E", "Socket connected");
        DOS.writeUTF(s);
        clientsocket.close();
    } catch (UnknownHostException e) {
        System.err.println("Don't know about host " + hostName);
        new Runnable() {
            public void run() {
                Toast.makeText(context, "Don't know about host " + hostName, Toast.LENGTH_SHORT).show();
            }
        };

    } catch (IOException e) {
        System.err.println("Couldn't get I/O for the connection to " + hostName);
        //Toast can not be run using asynctask since it acesses UI
        new Runnable() {
            public void run() {
                Toast.makeText(context, "Couldn't get I/O for the connection to " + hostName + " , check the port", Toast.LENGTH_SHORT).show();
            }
        };

    } catch (Exception e) {
        Log.d("E", "#fares" + e.getClass().getName().toString());

    }
    return null;
}

On 3 occasions do I try to send the string, all triggered from my seekbar (I send the seek bar progress value as my string): public void onProgressChanged(SeekBar seekBar, int i, boolean b) public void onStartTrackingTouch(SeekBar seekBar) public void onStopTrackingTouch(SeekBar seekBar)

The implementation for all 3 is the same: public void onProgressChanged(SeekBar seekBar, int i, boolean b) {

                    progressvalue = i;
                    textView.setText("Brightness = " + progressvalue + " %");


                    if (((RecieverPort.equals("Please enter port Number")) || (RecieverIP.equals("Please enter receiver IP")))) {

                        //Make sure toast isn't persistent
                        if (IPPortToastcount++ == 0)
                            Toast.makeText(MainActivity.this, "Please set both IP and Port ", Toast.LENGTH_SHORT).show();

                    } else {
                        //Check if connected to internet
                        if (!isConnectedtoInternet(MainActivity.this)) {
                            if (ConnectivityToastCount++ < 1)
                                Toast.makeText(MainActivity.this, "You are not connected to the Internet", Toast.LENGTH_SHORT).show();
                        } else {
                            //Send text over wifi
                            SendText ST = new SendText(getApplicationContext());
                            ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
                            ST.cancel(false);


                        }

                    }


                }

Mainly

//Send text over wifi
                            SendText ST = new SendText(getApplicationContext());
                            ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
                            ST.cancel(false);

The server side (my pc) is pretty simple:

int portNumber =  44339; // Choose unused port on router
    //Open a socket

    try {

        //System.out.println("in try statement");
        try (ServerSocket serverSocket1 = new ServerSocket(portNumber)) { 
            portNumber = serverSocket1.getLocalPort();
           System.out.println("Created socket at port " + portNumber);
            Socket clientSocket = serverSocket1.accept();

            System.out.println("Accepted");

            DataInputStream DIS = new DataInputStream(clientSocket.getInputStream()); //get input from socket
            //System.out.println("Created reader");

            String inputLine;


           // System.out.println("About to read");


            while (DIS.available() > 0) {
                inputLine = DIS.readUTF();
                System.out.println(inputLine);
            }


        }
    } catch (Exception e) {
        System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
        System.out.println(e.getClass().getSimpleName());
    }

This kind of works, except it takes a very long time(seconds) before the server socket is accepted. It also only works in onprogresschanged , which leads me to believe that multiple attempts of

//Send text over wifi
                            SendText ST = new SendText(getApplicationContext());
                            ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
                            ST.cancel(false);

are needed before one succeeds at creating the socket and connecting to the pc. How can I make sure that one tap, or one call of the function will be enough to send the string? Sorry for the long post but it's my first time asking :)

Edit: my new server code:

try {

        //System.out.println("in try statement");
        try ( ServerSocket serverSocket1 = new ServerSocket(portNumber)) 
        { 
            portNumber = serverSocket1.getLocalPort();
           System.out.println("Created socket at port " + portNumber);
           while(true){
            Socket clientSocket = serverSocket1.accept();

           // System.out.println("Accepted");

            DataInputStream DIS = new DataInputStream(clientSocket.getInputStream()); //get input from socket
            //System.out.println("Created reader");

            //String inputLine;


           //System.out.println("About to read");
           System.out.println(DIS.readUTF());


            }


        }
    } catch (Exception e) {
        System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
        System.out.println(e.getClass().getSimpleName());
    }

Worth noting that even in the while true loop, the server will always display 4 numbers then stop.

Edit: here is an example log: 10-06 20:08:09.145 26372-26372/com.example.fares.ledslider D/E: #fares in test method value = 50 10-06 20:08:26.475 26372-26372/com.example.fares.ledslider D/E: #Fares in start tracking 10-06 20:08:26.722 26372-27004/com.example.fares.ledslider D/E: #fares Socket connected 10-06 20:08:26.810 26372-26764/com.example.fares.ledslider D/E: #fares Socket connected 10-06 20:08:27.241 26372-27003/com.example.fares.ledslider D/E: #fares Socket connected 10-06 20:08:27.304 26372-26372/com.example.fares.ledslider D/E: #fares in stop tracking

1
So your server closes once one client connected. Further clients cannot connect. You should make a loop for the server so it waits for the next client when one is done. - greenapps
The loop should start with Socket clientSocket = serverSocket1.accept(); - greenapps
Just use a button to launch one asynctask. Then see how long it takes to connect. - greenapps
Any idee how many asynctasks you launch when the user moves the slider? - greenapps
@greenapps I'll answer in bullet points, and thanks for your help :) - I added a loop, it works better but still not fast -If i tap somewhere on the seekbar, that's as good as pressing a button, it doesn't connect. -The number of asynctaks is variable, it depends on the change of seekbar progress value, I.E., if it goes from 100 to 99 it is 3. In total the formula NumberOfAsyncTasksLaunched= ChangeInSeekBarProgress + 2 - Fares Ghazy

1 Answers

0
votes

ST.cancel() can be removed. Also not waiting for availability looks not good.