├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── jarRepositories.xml └── misc.xml ├── Notes.md ├── README.md ├── Server Class └── Server.java ├── TcpClientApp.apk ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── appclient │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── appclient │ │ │ ├── MainActivity.java │ │ │ └── connect_to_server.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout-land │ │ └── activity_main.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── appclient │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /Notes.md: -------------------------------------------------------------------------------- 1 | # [Notes](https://hackmd.io/@Q4x1OboORY-yKLhWsxCdQg/SylcS64Xv) 2 | 3 | App Development 4 | === 5 | 6 | ## Table of Contents 7 | * [App Development](#App-Development) 8 | * [Table of Contents](#Table-of-Contents) 9 | * [1.Intents (Explicit)](#1-intents-explicit "Goto Intents") 10 | * [2.Handler](#2-Handler "Goto Handler") 11 | * [3.AsynTask](#3-AsynTask "Goto AsynTask") 12 | * [4.TCP Communication](#4-TCP-Communication "Goto TCP Communication") 13 | * [5.Others](#5-others "Goto Others") 14 | 15 | ## 1. Intents (Explicit) 16 | Link: [Javapoint Android Explicit Intents](https://www.javatpoint.com/android-explicit-intent-example) 17 | 18 | * Simple Intent 19 | ```js 20 | Intent i = new Intent(getApplicationContext(), ActivityTwo.class); 21 | startActivity(i); 22 | ``` 23 | * Adding Extras to intent 24 | *Code in Main Activity* 25 | ```js 26 | public void callSecondActivity(View view){ 27 | Intent i = new Intent(getApplicationContext(), SecondActivity.class); 28 | i.putExtra("Value1", "Android By Javatpoint"); 29 | i.putExtra("Value2", "Simple Tutorial"); 30 | startActivity(i); 31 | } 32 | ``` 33 | 34 | *Code in Second Activity* 35 | ```js 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_second); 40 | Intent intent = getIntent(); 41 | String value1 = intent.getStringExtra("Value1"); 42 | String value2 = intent.getStringExtra("Value2"); 43 | Toast.makeText(getApplicationContext(),"Values are:\n First value: "+value1+ 44 | "\n Second Value: "+value2, Toast.LENGTH_LONG).show(); 45 | } 46 | ``` 47 | * Intent Activity for result 48 | 49 | 50 | *There are two variants of startActivityForResult() method.* 51 | ```js 52 | public void startActivityForResult (Intent intent, int requestCode) 53 | public void startActivityForResult (Intent intent, int requestCode, Bundle options) 54 | ``` 55 | 56 | *Code in Main Activity* 57 | ```js 58 | @Override 59 | protected void onCreate(Bundle savedInstanceState) { 60 | super.onCreate(savedInstanceState); 61 | setContentView(R.layout.activity_main); 62 | textView1=(TextView)findViewById(R.id.textView1); 63 | button1=(Button)findViewById(R.id.button1); 64 | button1.setOnClickListener(new OnClickListener() { 65 | @Override 66 | public void onClick(View arg0) { 67 | Intent intent=new Intent(MainActivity.this,SecondActivity.class); 68 | startActivityForResult(intent, 2);// Activity is started with requestCode 2 69 | } 70 | }); 71 | } 72 | // Call Back method to get the Message form other Activity 73 | @Override 74 | protected void onActivityResult(int requestCode, int resultCode, Intent data) 75 | { 76 | super.onActivityResult(requestCode, resultCode, data); 77 | // check if the request code is same as what is passed here it is 2 78 | if(requestCode==2) 79 | { 80 | String message=data.getStringExtra("MESSAGE"); 81 | textView1.setText(message); 82 | } 83 | } 84 | ``` 85 | 86 | *Code in Second Activity* 87 | ```js 88 | @Override 89 | protected void onCreate(Bundle savedInstanceState) { 90 | super.onCreate(savedInstanceState); 91 | setContentView(R.layout.activity_second); 92 | editText1=(EditText)findViewById(R.id.editText1); 93 | button1=(Button)findViewById(R.id.button1); 94 | button1.setOnClickListener(new OnClickListener() { 95 | @Override 96 | public void onClick(View arg0) { 97 | String message=editText1.getText().toString(); 98 | Intent intent=new Intent(); 99 | intent.putExtra("MESSAGE",message); 100 | setResult(2,intent); 101 | finish();//finishing activity 102 | } 103 | }); 104 | } 105 | ``` 106 | 107 | ## 2. Handler 108 | Link: [Android Developer Handler Class](https://developer.android.com/reference/android/os/Handler) 109 | There are two main uses for a Handler: (1) to schedule messages and runnables to be executed at some point in the future; and (2) to enqueue an action to be performed on a different thread than your own. 110 | 111 | 112 | * `postDelayed(Runnable r, long delayMillis)` 113 | 114 | Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. 115 | 116 | ## 3. AsynTask 117 | Link: [Android Developer AsyncTask Class](https://developer.android.com/reference/android/os/AsyncTask) 118 | Link: [Stackoverflow AsyncTask Example](https://stackoverflow.com/questions/9671546/asynctask-android-example) 119 | Android AsyncTask going to do background operation on background thread and update on main thread. 120 | 121 | ## 4. TCP Communication 122 | Link: [Tutorialspoint sending and recieving using Sockets in Android](https://www.tutorialspoint.com/sending-and-receiving-data-with-sockets-in-android) 123 | 124 | ## 5. Others 125 | * #### Making TextView Scrollable 126 | ```xml 127 | 129 | ``` 130 | ```js 131 | textView.setMovementMethod(newScrollingMovementMethod()); 132 | ``` 133 | 134 | ###### tags: `App Development` `Notes` `Documentation` `Templates` 135 | 136 | --- 137 | [Back to Top](#Notes) 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android_TCP_Client_Application 2 | The app establish a TCP communication between PC and Android device. 3 | 4 | *Click [here](https://github.com/ABD-01/Android_TCP_Client_Application/raw/master/TcpClientApp.apk) to download the .apk file.* 5 | 6 | See my [Notes](https://hackmd.io/@ABD/SylcS64Xv) 7 | 8 | # Start a Server (in PC/Laptop) 9 | #### 1.Using Java Server Class 10 | 1. Download the following Server.java file from [here](https://raw.githubusercontent.com/ABD-01/Android_TCP_Client_Application/master/Server%20Class/Server.java). 11 | 2. Compile the file using `javac Server.java`. 12 | 3. Run it using command line argument where second argument is *Port No.(eg. port no : 6066)* `java Server 6066` 13 | 14 | ![cmd_java](https://user-images.githubusercontent.com/63636498/90413636-5b6c5d00-e0cc-11ea-818f-dc8cc948dc01.png) 15 | 16 | #### 2.Using NetCat 17 | 1. Download the netcat zip file from [here](https://joncraton.org/files/nc111nt.zip). 18 | 2. Extract the contents of the file and open that directory in terminal `cd Downloads/nc111nt`. 19 | 3. Run the following command: `nc.exe -nlvp 6066`, (where 6066 is port no. on which server is listening). 20 | 21 | ![cmd_nc](https://user-images.githubusercontent.com/63636498/90414724-c4a0a000-e0cd-11ea-8e65-5c8811970851.png) 22 | 23 | # Running the Client App and Starting the Connection 24 | 1. Enter the port no. and IP Address of your pc/laptop. 25 | image 26 | 27 | 2. Click `Connect` button. 28 | 29 | # Send Messages 30 | 1. Enter the message eg: `Hello to Server from Client`. 31 | 2. Hit 'Send'. 32 | 33 | ![image](https://user-images.githubusercontent.com/63636498/90417892-fca9e200-e0d1-11ea-92d1-ee2623cdb3df.png) 34 | 35 | # Closing Connection 36 | 1. Send the message `Over` to Server to close the sockets. 37 | -------------------------------------------------------------------------------- /Server Class/Server.java: -------------------------------------------------------------------------------- 1 | // A Java program for a Server 2 | import java.net.*; 3 | import java.io.*; 4 | 5 | public class Server 6 | { 7 | public static void main(String args[]) 8 | { 9 | if (args.length < 1) return; 10 | int port = Integer.parseInt(args[0]); 11 | 12 | // starts server and waits for a connection 13 | try 14 | { 15 | ServerSocket server = new ServerSocket(port); 16 | System.out.println("Server started at port: " + port); 17 | 18 | System.out.println("Waiting for a client ..."); 19 | 20 | Socket serverSocket = server.accept(); 21 | System.out.println("Client accepted " + serverSocket.getRemoteSocketAddress()); 22 | 23 | // takes input from the client socket 24 | InputStream inFromClient = serverSocket.getInputStream(); 25 | DataInputStream in = new DataInputStream(inFromClient); 26 | 27 | String line = ""; 28 | 29 | // reads message from client until "Over" is sent 30 | while (!line.equals("Over")) 31 | { 32 | try 33 | { 34 | line = in.readUTF(); 35 | System.out.println(line); 36 | 37 | } 38 | catch(IOException i) 39 | { 40 | System.out.println(i); 41 | } 42 | } 43 | System.out.println("Closing connection"); 44 | 45 | // close connection 46 | serverSocket.close(); 47 | in.close(); 48 | } 49 | catch(IOException i) 50 | { 51 | System.out.println(i); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /TcpClientApp.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ABD-01/Android_TCP_Client_Application/18c4dd7cb40d3a12ca2fc6202ecca5d567b4226d/TcpClientApp.apk -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "30.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.example.appclient" 9 | minSdkVersion 16 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: "libs", include: ["*.jar"]) 27 | implementation 'androidx.appcompat:appcompat:1.1.0' 28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 29 | testImplementation 'junit:junit:4.12' 30 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 32 | 33 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/appclient/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.appclient; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.example.appclient", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/appclient/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.appclient; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | import android.widget.Toast; 11 | 12 | import java.util.concurrent.ExecutionException; 13 | 14 | public class MainActivity extends AppCompatActivity { 15 | 16 | private static final String LOG_TAG = MainActivity.class.getSimpleName(); 17 | private EditText ipAdd; 18 | private EditText sport; 19 | private Button button; 20 | private Button button2; 21 | 22 | connect_to_server connect; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_main); 28 | ipAdd = findViewById(R.id.ipAdd); 29 | sport = findViewById(R.id.sport); 30 | button = findViewById(R.id.button); 31 | button2 = findViewById(R.id.button2); 32 | button2.setVisibility(View.INVISIBLE); 33 | } 34 | 35 | public void connectToServer(View view) { 36 | Log.d(LOG_TAG, "'Connect' Button clicked!"); 37 | if (ipAdd.getText().toString().equals("") || sport.getText().toString().equals("")) { 38 | Toast.makeText(this, "Fields cannot be empty.", Toast.LENGTH_SHORT).show(); 39 | return; 40 | } 41 | 42 | connect = new connect_to_server(); 43 | connect_to_server.LOG_TAG = LOG_TAG; 44 | connect_to_server.context = this; 45 | connect_to_server.ip = ipAdd.getText().toString(); 46 | connect_to_server.port = Integer.parseInt(sport.getText().toString()); 47 | Log.d(LOG_TAG, "IP Address is " + ipAdd.getText().toString()); 48 | 49 | connect.execute(); 50 | String returned = ""; 51 | try { 52 | returned = connect.get(); 53 | } catch (ExecutionException e) { 54 | Log.d(LOG_TAG, e.toString()); 55 | } catch (InterruptedException e) { 56 | Log.d(LOG_TAG, e.toString()); 57 | } 58 | Log.d(LOG_TAG, "Message returned : " + returned); 59 | 60 | if (!returned.equals("connected")){ 61 | Toast.makeText(this, "Unable to Connect\nTry Again", Toast.LENGTH_LONG).show(); 62 | } 63 | else { 64 | sport.setVisibility(View.INVISIBLE); 65 | ipAdd.setText(""); 66 | ipAdd.setHint("Message"); 67 | button.setVisibility(View.INVISIBLE); 68 | button2.setVisibility(View.VISIBLE); 69 | } 70 | } 71 | 72 | public void sendMessage(View view) { 73 | connect = new connect_to_server(); 74 | connect.message = ipAdd.getText().toString(); 75 | try 76 | { 77 | connect.execute(); 78 | } 79 | catch (Exception e){ 80 | Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); 81 | Log.d(LOG_TAG, "Exception in MainActivity: " + e.toString()); 82 | } 83 | if (connect.message.equalsIgnoreCase("Over")) { 84 | sport.setVisibility(View.VISIBLE); 85 | sport.setText(""); 86 | ipAdd.setHint("IPv4"); 87 | button.setVisibility(View.VISIBLE); 88 | button2.setVisibility(View.INVISIBLE); 89 | } 90 | ipAdd.setText(""); 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/appclient/connect_to_server.java: -------------------------------------------------------------------------------- 1 | package com.example.appclient; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | import android.widget.Toast; 7 | 8 | import java.io.*; 9 | import java.net.*; 10 | 11 | public class connect_to_server extends AsyncTask { 12 | 13 | static String LOG_TAG; 14 | static Context context; 15 | static String ip; 16 | static int port; 17 | static String connected = "failed"; 18 | 19 | String message = "This is a test message is from Client Application."; 20 | String toast_message = "Message Sent"; 21 | 22 | static Socket clientSocket; 23 | static OutputStream outToServer; 24 | static DataOutputStream out; 25 | 26 | @Override 27 | protected String doInBackground(Void... voids) { 28 | connectToServer(ip, port); 29 | return connected; 30 | } 31 | 32 | void connectToServer(String ip, int port) { 33 | Log.d(LOG_TAG, "entered this activity"); 34 | try 35 | { 36 | if (!(connected.equals("connected"))) { 37 | clientSocket = new Socket(ip, port); 38 | toast_message = "This client is connected to " + clientSocket.getRemoteSocketAddress(); 39 | Log.d(LOG_TAG, toast_message); 40 | connected = "connected"; 41 | 42 | outToServer = clientSocket.getOutputStream(); 43 | out = new DataOutputStream(outToServer); 44 | } 45 | out.writeUTF(message + "\n"); 46 | if (message.equalsIgnoreCase("Over")) { 47 | toast_message = "Closing Connection"; 48 | out.close(); 49 | clientSocket.close(); 50 | connected = "completed"; 51 | } 52 | } 53 | catch(UnknownHostException u) 54 | { 55 | toast_message = "UnknownHostException: " + u.toString(); 56 | Log.d(LOG_TAG, toast_message); 57 | } 58 | catch(IOException i) 59 | { 60 | toast_message = " IOException: " + i.toString(); 61 | Log.d(LOG_TAG, toast_message ); 62 | } 63 | catch (Exception e) 64 | { 65 | toast_message = "Exception: " + e.toString(); 66 | Log.d(LOG_TAG, toast_message ); 67 | } 68 | } 69 | 70 | @Override 71 | protected void onPostExecute(String s) { 72 | super.onPostExecute(s); 73 | Toast.makeText(context, toast_message, Toast.LENGTH_SHORT).show(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 24 | 25 | 37 | 38 |