How make socket connection on Android

Question!

I'm trying to make a simple app that sends a message taken from an EditText, using the Java Socket class. I'm trying with AsyncTask, but it works only once and I can't return the socket for reuse in another instance of the class.

Can you give me an example of a background service that opens a communication with a server and returns the Socket?

EDIT:
As required by nandsito; I intend to open a connection using a Button, so this button calls a beckground process that creates the connection with the server, finally returns the Socket. When I press another Button I want to start another task that reuses sockets, write data (for example Sring) receive a response from the server and updates the UI.



Answers

It looks simple but I think you have an interesting and challenging problem. If you want to keep the socket open after sending messages through it, you'll need to maintain one or more threads to use that socket because, you know, Android doesn't allow networking on main thread.

Multithread programming is seldom simple and often there is more than one way to do it. E.g. in Android you can use Handlers with Loopers from HandlerThreads, or the classic Java Thread. And also AsyncTask, but I think it doesn't fit this case.

How do you intend to manage the socket lifecycle (i.e. when is it opened or closed), and in which moments is data read/written from/into the socket? Please explain better the matter so I can suggest an implementation.

EDIT

Here's an example Activity with two buttons. One button runs an AsyncTask that creates a socket and its streams, and the other button runs another AsyncTask that writes data into the socket. It's an oversimplified solution, but it should work. Note that the code needs synchronization, for different threads access the socket.

public class MainActivity extends Activity {

    private SocketContainer mSocketContainer;
    private final Object mSocketContainerLock = new Object();

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

    // onClick attribute of one button.
    public void onClickPushMe(View view) {
        String serverAddress;
        int serverPort;
        new CreateSocketAsyncTask(serverAddress, serverPort).execute();
    }

    // onClick attribute of other button.
    public void onClickPushMeToo(View view) {
        String text;
        new WriteSocketAsyncTask(text).execute();
    }

    // Class that contains the socket and its streams,
    // so they can be passed from one thread to another.
    private class SocketContainer {

        private Socket mSocket;
        private InputStream mSocketInputStream;
        private OutputStream mSocketOutputStream;

        private SocketContainer(Socket socket, InputStream socketInputStream, OutputStream socketOutputStream) {
            mSocket = socket;
            mSocketInputStream = socketInputStream;
            mSocketOutputStream = socketOutputStream;
        }

        private Socket getSocket() {
            return mSocket;
        }

        private InputStream getSocketInputStream() {
            return mSocketInputStream;
        }

        private OutputStream getSocketOutputStream() {
            return mSocketOutputStream;
        }
    }

    // AsyncTask that creates a SocketContainer and sets in into MainActivity.
    private class CreateSocketAsyncTask extends AsyncTask<Void, Void, SocketContainer> {

        private final String mServerAddress;
        private final int mServerPort;

        private CreateSocketAsyncTask(String serverAddress, int serverPort) {
            mServerAddress = serverAddress;
            mServerPort = serverPort;
        }

        protected SocketContainer doInBackground(Void... params) {
            try {
                Socket socket = new Socket(mServerAddress, mServerPort);
                return new SocketContainer(socket, socket.getInputStream(), socket.getOutputStream());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        protected void onPostExecute(SocketContainer socketContainer) {
            super.onPostExecute(socketContainer);
            synchronized (mSocketContainerLock) {
                mSocketContainer = socketContainer;
            }
        }
    }

    private class WriteSocketAsyncTask extends AsyncTask<Void, Void, Void> {

        private final String mText;

        private WriteSocketAsyncTask(String text) {
            mText = text;
        }

        @Override
        protected Void doInBackground(Void... params) {
            synchronized (mSocketContainerLock) {
                try {
                    mSocketContainer.getSocketOutputStream().write(mText.getBytes(Charset.forName("UTF-8")));
                    mSocketContainer.getSocketOutputStream().flush();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return null;
        }
    }
}
By : nandsito


Async task is not worthy for the real time chat. Get into firebase to use the things easy. This might help you- https://www.firebase.com/docs/android/examples.html

By : Amit Soni


With this code i connect to a chat, so you can use it similliary to connect with what you want

 public class SocialConnectionManager extends AsyncTask<Void, Void, Void> {

    public static final int SQL_STEP_LOGIN = 0;
    public static final int SQL_STEP_LOGOUT = 1;
    public static final int SQL_STEP_SEND = 2;
    public static final int SQL_STEP_UPDATE = 3;

    final int serverPort = 8080;
    private String message, channel, userName, serverIp;
    private int step;
    private long uniqueId;
    private Activity activity;

    public SocialConnectionManager(String serverIp, long uniqueId, int step, String userName,
                                   String channel, String message, Activity activity) {
        this.message = message;
        this.step = step;
        this.uniqueId = uniqueId;
        this.channel = channel;
        this.userName = userName;
        this.serverIp = serverIp;
        this.activity = activity;
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        Socket socket = null;

        try {
            socket = new Socket(serverIp, serverPort);
            DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream());
            switch (step) {
                case SQL_STEP_LOGIN:
                    dataOut.writeInt(step);
                    dataOut.writeLong(uniqueId);
                    dataOut.writeUTF(channel);
                    dataOut.writeUTF(userName);
                    break;
                case SQL_STEP_LOGOUT:
                    dataOut.writeInt(step);
                    dataOut.writeLong(uniqueId);
                    dataOut.writeUTF(channel);
                    dataOut.writeUTF(userName);
                    break;
                case SQL_STEP_SEND:
                    long messageId = createRandomId();
                    messageIds.add(messageId);
                    dataOut.writeInt(step);
                    dataOut.writeLong(uniqueId);
                    dataOut.writeUTF(channel);
                    dataOut.writeUTF(userName);
                    dataOut.writeUTF(message);
                    dataOut.writeLong(messageId);
                    break;
                case SQL_STEP_UPDATE:
                    dataOut.writeInt(step);
                    dataOut.writeUTF(message);
                    break;
            }
            dataOut.flush();

        } catch (UnknownHostException e) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ((MainActivity) activity).showNetworkAlertDialog(context.getString
                            (R.string.social_chat_connection_failed));
                }
            });
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
    }
}

private class ReceiveTask extends AsyncTask {

    final int clientPort = 5050;

    @Override
    protected Object doInBackground(Object[] params) {
        try {
            serverSocket = new ServerSocket(clientPort);
            while (true) {
                final Socket socket = serverSocket.accept();
                DataInputStream dataIn = new DataInputStream(socket.getInputStream());
                final int step = dataIn.readInt();
                final int userCount = dataIn.readInt();
                final String message = dataIn.readUTF();
                final String userName = dataIn.readUTF();
                switch (step) {
                    case SocialConnectionManager.SQL_STEP_LOGIN:
                        if (isLogging) {
                            activity.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    showProgress(false);
                                }
                            });
                            isLogging = false;
                            isLoggedIn = true;
                        }
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                userCountView.setText(Integer.toString(userCount));
                                addMessage(message, userName, step);
                            }
                        });
                        break;
                    case SocialConnectionManager.SQL_STEP_LOGOUT:
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                addMessage(message, userName, step);
                            }
                        });
                        break;
                    case SocialConnectionManager.SQL_STEP_SEND:
                        messageId = dataIn.readLong();
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                addMessage(message, userName, step);
                            }
                        });
                        break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String ip = getIpAddress();
        if (ip.equals("")) {
            ((MainActivity) activity).showNetworkAlertDialog(context.getString
                    (R.string.social_chat_connection_lost));
        } else if (!deviceIp.equals(ip)) {
            SocialConnectionManager socialConnectionManager =
                    new SocialConnectionManager(serverIp, 0,
                            SocialConnectionManager.SQL_STEP_UPDATE, null, null, deviceIp,
                            activity);
            socialConnectionManager.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    }
};

}

By : Rodriquez


This video can help you solving your question :)
By: admin