How to make socket connection on Android
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 Handler
s with Looper
s from HandlerThread
s, 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;
}
}
}
Android socket connection using socket.io 0.9.0 version
Refer this github repository and I only can find this github repository that can work for socket 0.9 version.
It may help you.
Happy coding :)
Java Client Socket Connection in Android
In your application the NetworkOnMainThreadException is occurred. From the doc you ca see that
The exception that is thrown when an application attempts to perform a
networking operation on its main thread.
So you have to call your RunSocketClient method from another thread rather than the main thread. Use a handler or asynctask or different thread to perform this operation.
To know about good designing you can see this link
http://developer.android.com/training/articles/perf-anr.html
How to connect an android client to a server written in C?
Just use socket, both Android's Java and C have it. You can read the documentation.
Or, here's the fast way. Just create Android Socket client as https://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/ does and create server as https://www.tutorialspoint.com/unix_sockets/socket_server_example.htm does.
Here's the snippet:
client.java
package com.javacodegeeks.android.androidsocketclient;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
public class Client extends Activity {
private Socket socket;
private static final int SERVERPORT = 5000;
private static final String SERVER_IP = "10.0.2.2";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new ClientThread()).start();
}
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
@Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
server.c
in *NIX environment.
/*
C socket server example
*/
#include<stdio.h>
#include<string.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , read_size;
struct sockaddr_in server , client;
char client_message[2000];
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
//accept connection from an incoming client
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
puts("Connection accepted");
//Receive a message from client
while( (read_size = recv(client_sock , client_message , 2000 , 0)) > 0 )
{
//Send the message back to client
write(client_sock , client_message , strlen(client_message));
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
Android Studio Connect to Socket server
I managed to resolve this. I just made a thread inside a "Connection" class in Android Studio.
Inside "Connection" I have some class-level variables, which I use with the thread (The thread can't modify variables in the method the thread was created but it can read class-level variables) so the thread itself makes the connection with the socket server and saves the value taken to also a class-level variable.
In the main thread (in the same method that called the thread) I used a loop that looks at the thread status, if it has finished, reads the variable and applies it where I want.
Here the code:
public class Connection{
private String HOST = "83.xx.xx.xx";
private int PORT = 5010;
private Socket socket;
private DataOutputStream dos;
private DataInputStream dis;
boolean result;
String email;
public boolean userExists(String dev) throws InterruptedException { // true = exists, false = does not exist. dev is the email to search
this.email = dev;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
socket = new Socket(HOST, PORT);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream((socket.getInputStream()));
dos.writeInt(1); // 1 = Sends the option for telling the server that we want to search a user
dos.writeUTF(email); //Sends the email
result = dis.readBoolean(); // Recieve if email exists or not
socket.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Couldn't connect to server");
}
}
});
thread.start();
for (int c=0; c<25; c++){ //Wait for the thread to end
if (thread.isAlive()) {
//Thread hasn't finished yet...
Thread.sleep(100);
} else if (c == 24) {
//This would be a timeout
result = false;
} else {
//Thread has finished
break;
}
}
return result; // true in case server found the email, false in case it doesn't or in case of a timeout
}
I think another possibility could be making the thread just do the connection (and another one for closing it) and saving the socket as class-level variable, so you can send and receive from the main thread, I didn't try it tho.
How can I connect two Android device by socket without server
Java provides ServerSocket and Socket to communicate b/w devices. One of the device you can make as server and other device you can make as client and communicate b/w 'em without introducing server hosted on some machine.
The Other and better option is Using Wi-Fi Peer-to-Peer. WifiP2pManager help you to achieve your purpose.Here is an example.
Related Topics
How to Use Custom Permissions in Android
Failed Binder Transaction When Putting an Bitmap Dynamically in a Widget
Creating a Directory in /Sdcard Fails
Android:Static Fields and Memory Leaks
How to Open or Simulate a Click on an Android Preference, Created with Xml, Programmatically
Error: Could Not Find Com.Google.Gms:Google-Services:4.2.0
Androidstudio Cannot Find Layout
How to Generate an Md5 Checksum for a File in Android
More Efficient Way of Updating UI from Service Than Intents
No Activity Found to Handle Intent:Android.Intent.Action.View
How to Open/Display Documents(.Pdf, .Doc) Without External App
How to Set a Font for the Options Menu
Android Intercept Paste\Copy\Cut on Edittext
How to Automatically Add Thousand Separators as Number Is Input in Edittext
Removecallbacks Not Stopping Runnable
How to Add Buttons at Top of Map Fragment API V2 Layout
Launch Android Application Without Main Activity and Start Service on Launching Application