shallawati
shallawati

Reputation: 145

Receive message through: Android to Python Socket

So I am developing an Android application which connects to a server (written in Python) via a socket. Android sends an image to the server and expects a text message in return, then it updates a TextView to display the received message.

What happens is: that the server receives the image successfully and sends back a message. For some reason the message is not displayed on the Android app.

I cannot figure out, is it because the app didn't receive the message? Or did receive it but the message and the error was with displaying the message?

Here is the server's code (server.py):

from socket import *

HOST = "x.x.x.x" #replaced with the server's IP
PORT = 6000
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print "Connected by: " , addr
while True:
    data = conn.recv(40960)
    with open('image.jpg', 'wb') as file:
       file.write(data)
    reply = raw_input("Reply: ")
    conn.sendall(reply)
conn.close() 

And this is a snippet of the code for the Android app:

static TextView msgReceived;

    public void onClickSend(View view) {

        Thread t = new Thread(new Runnable(){

            String imgPath = "/mnt/sdcard/Pictures/0001.jpg";

            @Override
            public void run() {
                try {
                    Socket s = new Socket("x.x.x.x", 6000); //create socket

                    //---- SEND IMAGE TO SERVER ---//
                    FileInputStream fis = new FileInputStream(imgPath); //read image as bytes
                    byte [] buffer1 = new byte [fis.available()]; //create buffer that will hold the bytes
                    fis.read(buffer1); //read file contents to the buffer

                    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); //create the object to be sent
                    oos.writeObject(buffer1); //send the contents of the buffer to the socket
                    oos.close();

                    //---- RECEIVE TEXT FROM SERVER ---//
                    tempIn = new ObjectInputStream(s.getInputStream());
                        Message clientmessage = Message.obtain();                    
                        ObjectInputStream ois = new ObjectInputStream(tempIn);
                        String strMessage = (String)ois.readObject();
                        System.out.println(strMessage);
                        clientmessage.obj = strMessage;

                        mHandler.sendMessage(clientmessage);

                        ois.close();

                    s.close();

                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } //catch (ClassNotFoundException e) {
                    //e.printStackTrace();
                //}
            }

        });

        t.start();
    }

    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            Display(msg.toString());
        }
    };

    public void Display(String serverMsg){
        msgReceived = (EditText) findViewById(R.id.msgReceived);
        msgReceived.setText(serverMsg);
        //Toast.makeText(getBaseContext(), serverMsg, Toast.LENGTH_SHORT).show();
    }

I believe the problem is with the Android java code because the server.py worked successfully with a test client.py (i.e. it received an image from it, sent back a reply and the client received it perfectly). One more addition, while I was troubleshooting the problem, I tried to update TextView with a normal string (not the one received from the server) and it did not work! So that might indicate that the source of the problem is the updating part. I would appreciate any help and thank you in advance. I am very new to Android developing and java.

Upvotes: 0

Views: 2231

Answers (1)

savanto
savanto

Reputation: 4550

Your problem is two-fold:

  1. You call oos.close() right after writing the image to the socket. I found that this was throwing a SocketException: Socket is closed. According to this answer: Android: Socket is closed, closing a stream associated with a socket will close that socket, and you won't be able to read the server's response from it. So, move oos.close() to the very end, after you are done reading.

  2. After I made that modification to your code, it still threw a StreamCorruptedException. According to this answer from StreamCorruptedException: invalid type code: AC, this happens because you used two ObjectInput/OutputStreams. I'm not really sure how to use just one, unless you go with the modification that I suggested earlier. I reworked your code to the following which works on my system using your python server code.

    // Write to socket
    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); //create the object to be sent
    oos.writeObject(buffer1); //send the contents of the buffer to the socket    
    oos.flush();
    
    // Read from socket
    BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
    StringBuilder response = new StringBuilder();
    String line;
    while ((line = input.readLine()) != null)
        response.append(line);
    Message clientmessage = Message.obtain();
    clientmessage.obj = response.toString();
    mHandler.sendMessage(clientmessage);
    oos.close();
    input.close();
    s.close();
    

By the way, you define the UI element msgReceived as a TextView at the top, but cast it to EditView at the bottom of your code. I got a ClassCastException, until I changed them to match each other, so be careful.

Upvotes: 1

Related Questions