how to create Socket connection in Android?

AndroidSockets

Android Problem Overview


I have an application in which I need to create a socket connection. My requirement is: once my socket connection is established it needs to be alive until I personally close it. And every 3 minutes I have to send data packets to the other end. Can anyone provide me some code samples that will help me to do this?

Android Solutions


Solution 1 - Android

Socket connections in Android are the same as in Java: http://www.oracle.com/technetwork/java/socket-140484.html

Things you need to be aware of:

  1. If phone goes to sleep your app will no longer execute, so socket will eventually timeout. You can prevent this with wake lock. This will eat devices battery tremendously - I know I wouldn't use that app.
  2. If you do this constantly, even when your app is not active, then you need to use Service.
  3. Activities and Services can be killed off by OS at any time, especially if they are part of an inactive app.

Take a look at AlarmManager, if you need scheduled execution of your code.

Do you need to run your code and receive data even if user does not use the app any more (i.e. app is inactive)?

Solution 2 - Android

Here, in this post you will find the detailed code for establishing socket between devices or between two application in the same mobile.

You have to create two application to test below code.

In both application's manifest file, add below permission

<uses-permission android:name="android.permission.INTERNET" />

>1st App code: Client Socket

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<TableRow
		android:id="@+id/tr_send_message"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:gravity="center"
		android:layout_alignParentLeft="true"
		android:layout_alignParentStart="true"
		android:layout_alignParentTop="true"
		android:layout_marginTop="11dp">

		<EditText
			android:id="@+id/edt_send_message"
			android:layout_width="0dp"
			android:layout_height="wrap_content"
			android:layout_weight="1"
			android:layout_marginRight="10dp"
			android:layout_marginLeft="10dp"
			android:hint="Enter message"
			android:inputType="text" />

		<Button
			android:id="@+id/btn_send"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:layout_marginRight="10dp"
			android:text="Send" />
	</TableRow>

	<ScrollView
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:layout_alignParentLeft="true"
		android:layout_alignParentStart="true"
		android:layout_below="@+id/tr_send_message"
		android:layout_marginTop="25dp"
		android:id="@+id/scrollView2">

		<TextView
			android:id="@+id/tv_reply_from_server"
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:orientation="vertical" />
	</ScrollView>
</RelativeLayout>

MainActivity.java

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * Created by Girish Bhalerao on 5/4/2017.
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

	private TextView mTextViewReplyFromServer;
	private EditText mEditTextSendMessage;

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

		Button buttonSend = (Button) findViewById(R.id.btn_send);

		mEditTextSendMessage = (EditText) findViewById(R.id.edt_send_message);
		mTextViewReplyFromServer = (TextView) findViewById(R.id.tv_reply_from_server);

		buttonSend.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {

		switch (v.getId()) {

			case R.id.btn_send:
				sendMessage(mEditTextSendMessage.getText().toString());
				break;
		}
	}

	private void sendMessage(final String msg) {

		final Handler handler = new Handler();
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {

				try {
					//Replace below IP with the IP of that device in which server socket open.
					//If you change port then change the port number in the server side code also.
					Socket s = new Socket("xxx.xxx.xxx.xxx", 9002);

					OutputStream out = s.getOutputStream();

					PrintWriter output = new PrintWriter(out);

					output.println(msg);
					output.flush();
					BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
					final String st = input.readLine();

					handler.post(new Runnable() {
						@Override
						public void run() {

							String s = mTextViewReplyFromServer.getText().toString();
							if (st.trim().length() != 0)
								mTextViewReplyFromServer.setText(s + "\nFrom Server : " + st);
						}
					});

					output.close();
					out.close();
					s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});

		thread.start();
	}
}

>2nd App Code - Server Socket

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<Button
		android:id="@+id/btn_stop_receiving"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="STOP Receiving data"
		android:layout_alignParentTop="true"
		android:enabled="false"
		android:layout_centerHorizontal="true"
		android:layout_marginTop="89dp" />

	<ScrollView
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:layout_below="@+id/btn_stop_receiving"
		android:layout_marginTop="35dp"
		android:layout_alignParentLeft="true"
		android:layout_alignParentStart="true">

		<TextView
			android:id="@+id/tv_data_from_client"
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:orientation="vertical" />
	</ScrollView>

	<Button
		android:id="@+id/btn_start_receiving"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="START Receiving data"
		android:layout_alignParentTop="true"
		android:layout_centerHorizontal="true"
		android:layout_marginTop="14dp" />
</RelativeLayout>

MainActivity.java

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by Girish Bhalerao on 5/4/2017.
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

	final Handler handler = new Handler();

	private Button buttonStartReceiving;
	private Button buttonStopReceiving;
	private TextView textViewDataFromClient;
	private boolean end = false;

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

		buttonStartReceiving = (Button) findViewById(R.id.btn_start_receiving);
		buttonStopReceiving = (Button) findViewById(R.id.btn_stop_receiving);
		textViewDataFromClient = (TextView) findViewById(R.id.tv_data_from_client);

		buttonStartReceiving.setOnClickListener(this);
		buttonStopReceiving.setOnClickListener(this);

	}

	private void startServerSocket() {

		Thread thread = new Thread(new Runnable() {

			private String stringData = null;

			@Override
			public void run() {

				try {

					ServerSocket ss = new ServerSocket(9002);

					while (!end) {
						//Server is waiting for client here, if needed
						Socket s = ss.accept();
						BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
						PrintWriter output = new PrintWriter(s.getOutputStream());

						stringData = input.readLine();
						output.println("FROM SERVER - " + stringData.toUpperCase());
						output.flush();

						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						updateUI(stringData);
						if (stringData.equalsIgnoreCase("STOP")) {
							end = true;
							output.close();
							s.close();
							break;
						}

						output.close();
						s.close();
					}
					ss.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

		});
		thread.start();
	}

	private void updateUI(final String stringData) {

		handler.post(new Runnable() {
			@Override
			public void run() {

				String s = textViewDataFromClient.getText().toString();
				if (stringData.trim().length() != 0)
					textViewDataFromClient.setText(s + "\n" + "From Client : " + stringData);
			}
		});
	}

	@Override
	public void onClick(View v) {

		switch (v.getId()) {
			case R.id.btn_start_receiving:

				startServerSocket();
				buttonStartReceiving.setEnabled(false);
				buttonStopReceiving.setEnabled(true);
				break;

			case R.id.btn_stop_receiving:

				//stopping server socket logic you can add yourself
				buttonStartReceiving.setEnabled(true);
				buttonStopReceiving.setEnabled(false);
				break;
		}
	}
}

Solution 3 - Android

Simple socket server app example

I've already posted a client example at: https://stackoverflow.com/a/35971718/895245 , so here goes a server example.

This example app runs a server that returns a ROT-1 cypher of the input.

You would then need to add an Exit button + some sleep delays, but this should get you started.

To play with it:

Android sockets are the same as Java's, except we have to deal with some permission issues.

src/com/cirosantilli/android_cheat/socket/Main.java

package com.cirosantilli.android_cheat.socket;

import android.app.Activity;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Main extends Activity {
    static final String TAG = "AndroidCheatSocket";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(Main.TAG, "onCreate");
        Main.this.startService(new Intent(Main.this, MyService.class));
    }

    public static class MyService extends IntentService {
        public MyService() {
            super("MyService");
        }
        @Override
        protected void onHandleIntent(Intent intent) {
            Log.d(Main.TAG, "onHandleIntent");
            final int port = 12345;
            ServerSocket listener = null;
            try {
                listener = new ServerSocket(port);
                Log.d(Main.TAG, String.format("listening on port = %d", port));
                while (true) {
                    Log.d(Main.TAG, "waiting for client");
                    Socket socket = listener.accept();
                    Log.d(Main.TAG, String.format("client connected from: %s", socket.getRemoteSocketAddress().toString()));
                    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    PrintStream out = new PrintStream(socket.getOutputStream());
                    for (String inputLine; (inputLine = in.readLine()) != null;) {
                        Log.d(Main.TAG, "received");
                        Log.d(Main.TAG, inputLine);
                        StringBuilder outputStringBuilder = new StringBuilder("");
                        char inputLineChars[] = inputLine.toCharArray();
                        for (char c : inputLineChars)
                            outputStringBuilder.append(Character.toChars(c + 1));
                        out.println(outputStringBuilder);
                    }
                }
            } catch(IOException e) {
                Log.d(Main.TAG, e.toString());
            }
        }
    }
}

We need a Service or other background method or else: https://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.cirosantilli.android_cheat.socket"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="22" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:label="AndroidCheatsocket">
        <activity android:name="Main">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".Main$MyService" />
    </application>
</manifest>

We must add: <uses-permission android:name="android.permission.INTERNET" /> or else: https://stackoverflow.com/questions/4074808/java-socket-ioexception-permission-denied

On GitHub with a build.xml: https://github.com/cirosantilli/android-cheat/tree/92de020d0b708549a444ebd9f881de7b240b3fbc/socket

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNilanchala PanigrahyView Question on Stackoverflow
Solution 1 - AndroidPeter KnegoView Answer on Stackoverflow
Solution 2 - AndroidGirish BhaleraoView Answer on Stackoverflow
Solution 3 - AndroidCiro Santilli Путлер Капут 六四事View Answer on Stackoverflow