0

On Being a Duplicate: Please note that I have acknowledged other Q&As (Thread UI) but my case is different as I have tried to use the solution but it doesn't work at all instances (as it works for writing but doesn't for reading.

Updated: I know exactly what is going wrong please read the bold My Question part I'm trying to make an Android Socket Client that connects to a Java server via WiFi.The final client will send and receive commands and logs as there will be a textbox that user can write SQL commands in it and by hitting a button command will be sent from the app to the Desktop server and show the log in another textbox.

so far I have been trying to use This Answer from another question to make that Client, and adding following lines in the TCP client.

Scanner  in = new Scanner(socket.getInputStream());//in doInBackground
//also changed send method a little
public String send(String command)
{
    if ( connected ){
        out.println(command);
        out.flush();

        String back = in.nextLine().toString();
        return back;

    }
    return "not Connected";
}

The connection is made successfully and the send method does send the command while server receives it.but the String that server writes back throw the mentioned exception in the title despite the fact that I am using the AsyncTask.

My Question

Why Scanner throws this exception while PrintWriter works correctly ?

Main Activity

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {


EditText serverIP, servMsg;
String ip, serverOut;
Button connectBtn;
TcpClient tcpClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    serverIP = (EditText) findViewById(R.id.serverIP);
    connectBtn = (Button) findViewById(R.id.connectBtn);
    servMsg = (EditText) findViewById(R.id.servMsg);

}

public void onConnectBtn(View view){

    try{

        ip = serverIP.getText().toString();
        tcpClient = new TcpClient();
        tcpClient.connect(getApplicationContext(), ip, 8082);
        serverOut = tcpClient.send("HELLO FROM cat:123");
        servMsg.setText(serverOut);

        tcpClient.disconnect(getApplicationContext());

    }
    catch (Exception e){

        Toast.makeText(getApplicationContext(),
                "Exception on runnning thread: " + e.getMessage().toString(), Toast.LENGTH_LONG).show();

    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
  }
}

TCP Client

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

public class TcpClient {

private static final String TAG = TcpClient.class.getSimpleName();

private Socket socket;
private PrintWriter out;
private Scanner in;
private boolean connected;

public TcpClient() {
    socket = null;
    out = null;
    connected = false;
}


public void connect(Context context, String host, int port) {
    new ConnectTask(context).execute(host, String.valueOf(port));
}

private class ConnectTask extends AsyncTask<String, Void, Void> {

    private Context context;

    public ConnectTask(Context context) {
        this.context = context;
    }

    @Override
    protected void onPreExecute() {
        showToast(context, "Connecting..");
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void result) {
        if (connected) {
            showToast(context, "Connection successful");
        }
        super.onPostExecute(result);
    }

    private String host;
    private int port;

    @Override
    protected Void doInBackground(String... params) {
        try {
            String host = params[0];
            int port = Integer.parseInt(params[1]);
            socket = new Socket(host, port);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new Scanner(socket.getInputStream());
        } catch (UnknownHostException e) {
            showToast(context, "Don't know about host: " + host + ":" + port);
            Log.e(TAG, e.getMessage());
        } catch (IOException e) {
            showToast(context, "Couldn't get I/O for the connection to: " + host + ":" + port);
            Log.e(TAG, e.getMessage());
        }
        connected = true;
        return null;
    }


}

public void disconnect(Context context) {
    if (connected) {
        try {
            out.close();
            socket.close();
            connected = false;
        } catch (IOException e) {
            showToast(context, "Couldn't get I/O for the connection");
            Log.e(TAG, e.getMessage());
        }
    }
}


/**
 * Send command to a Pure Data audio engine.
 */
 public String send(String command)
{
    if ( connected ){
        out.println(command);
        out.flush();

        String back = in.nextLine().toString();
        return back;

    }
    return "not Connected";
}
private void showToast(final Context context, final String message) {
    new Handler(context.getMainLooper()).post(new Runnable() {

        @Override
        public void run() {
            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
        }
    });
  }
}

Also the Layout right now consist of two TextEdits one in which user types IP of the computer(which I checked with correct IPs) and the second one is going to show Server response.

Community
  • 1
  • 1
Vicarious
  • 131
  • 18
  • *"but my case is different as I have tried to use the solution but it doesn't work"* - That's probably because your didn't understand the solution and you applied it incorrectly. Re: your theory that output is working, you have shown us zero evidence to support this. (Hint: stack trace ...) – Stephen C Jul 26 '15 at 02:37
  • @StephenC I don't get your point exactly. It is not my theory. as I've said I have run and debugged the program. It runs the the write method and server which is also running(not theoretically but actually) receives the message. but after this the readline method is going to be executed which throws the exception – Vicarious Jul 26 '15 at 08:13

1 Answers1

0

I believe you are not "flushing", which is essentially forcing the buffer to empty out its contents. Please take a look at this working chat server/client code that uses TCP/IP. On a side note, I would recommend not extending ActionBarActivity because it is deprecated (Google says they will move away from it and won't be supporting it soon). Please see 3rd link.

ChatServer.java

ChatClient.java

ActionBar Activity deprecation

Community
  • 1
  • 1
Ryan Zhou
  • 126
  • 1
  • 5
  • I do not think that is the problem as I have used PrintWriter for the usual Java socket client I mentioned and no flush was needed. Also thank you for noting the deprecated class ,it came from the blank activity template – Vicarious Jul 25 '15 at 21:55