I'm trying to send a single string from android to pc and after a bit of research on this site and others I've found out about sockets and how to use them. I have written the server program that can receive strings sent to it. Below is the code.
//static ServerSocket variable
private static ServerSocket server;
//socket server port on which it will listen
private static int port = 9021;
public static void main(String [] args) throws IOException, ClassNotFoundException{
server = new ServerSocket(port);
while(true){
System.out.println("Waiting for client request." + InetAddress.getLocalHost());
Socket socket = server.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String message = (String)ois.readObject();
System.out.println("Message received: " + message);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi Client: " + message);
ois.close();
oos.close();
socket.close();
if(message.equalsIgnoreCase("exit")){
break;
}
}
System.out.println("Shutting down serve");
server.close();
}
I have tested this using a pc client program that sends string and have confirmed that this server script works. I am trying to now implement the same concept in android but facing a lot of trouble mostly due to the fact that the tutorials online for this task is very outdated (2-3 years) so nothing works as expected. Can anyone tell me how to write a very simple android app in which a single string is sent over socket?
From what I can see in the logcat, the outdated tutorials on the internet are not working because android has apparently introduced in recent versions a very aggressive process manager which monitors the behaviour of threads and if there is any repeated thread actions, it shuts it down without notice.
Edit: As per a solution I have implemented an asynctask. But now the server is not receiving and says Address already in use. I think it is because of socket address in my android code. Please help!
public class MainActivity extends Activity {
private Button button;
private EditText message;
private TextView finalResult;
//InetAddress host;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
message = (EditText) findViewById(R.id.et_time);
button = (Button) findViewById(R.id.btn_do_it);
finalResult = (TextView) findViewById(R.id.tv_result);
/*
try {
host = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
AsyncTaskRunner runner = new AsyncTaskRunner();
String msg = message.getText().toString();
runner.execute(msg);
}
});
}
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
Socket socket = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
int clientport = 8080;
String resp;
#Override
protected String doInBackground(String... params) {
publishProgress("Sending...");
String msg = params[0];
for(int i=0;i<=5;i++){
//establish socket connection to server
try {
socket = new Socket( "100.69.73.16",clientport);
//write to socket using Objectouputstream
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(msg+i);
oos.close();
socket.close();
Thread.sleep(100);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
resp = "Message has been sent";
return resp;
}
#Override
protected void onPostExecute(String result) {
finalResult.setText(result);
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(String... values) {
finalResult.setText(values[0]);
}
}
}
Ok so I solved the problem of 'address already used' by changing port number. Apparently the port number was being used by other programs on my laptop. So in retrospect for anyone checking on how to do this, you can use my above code and remember to change the port number in both codes to something similar. Also in my android code where the socket is opened, you can put in the local ip address (very important, google gives you external) for your computer.
Related
I'm newer programer in android .. I need help
to sending text between two phone by wifi
first : server
second :client
I'm searching more but i need Simple code and easy to help me
thnx for advance
I guess sockets is what you are looking for...
To create a socket in android the socket must be created in a thread.
Client side example:
private final String IP = "9.9.9.9";
private final int PORT = 8080;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new MainThread()).start();
}
class MainThread implements Runnable {
#Override
public void run() {
try {
InetAddress address = InetAddress.getByName(IP);
socket = new Socket(address,PORT);
new Thread(new GetThread()).start();
} catch (UnknownHostException e1){
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
class GetThread implements Runnable {
#Override
public void run() {
try {
InputStreamReader isR=new InputStreamReader(socket.getInputStream());
BufferedReader bfr=new BufferedReader(isR);
while(true) {
String textMessage = bfr.readLine();
// TODO: Insert logic which use the recived message (textMessage)
}
}
} catch (UnknownHostException e1){
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
In the thread, the socket is waiting for data to be sent (while(true)).
and the IP is the ip of the server (if you are connecting to your computer
with wifi, you should check your ip address with ipconfig in the command line).
That is my program in java for my android app. I tried to create tcp connection with tcp server. I can connect to server with another applications so that i can send and receive from tcp server. With my code and with my program i can send messages to server very eazy, but i have troubles with receiving messages from server.
private Socket socket;
private final int SERVERPORT = 6060;
private final String SERVER_IP = "192.168.0.8";
public TextView tv;
private PrintWriter out;
private InputStream in;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)this.findViewById(R.id.textView1);
new Thread(new ClientThread()).start();
}
Here is my problem i dont know how to receive strings or bytes from server. When i run my app on phone it closes the open window and say that program stop working. If i delete this section of code(public void ONCLICK2) i can transmit messages to server.
public void ONCLICK2(View view) {
try {
in=socket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte array[]=new byte[1];
try {
int i=in.read(array);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
So please help me with that section of code. How can i receive string send from TCP server.
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.editText1);
String str = et.getText().toString();
out.println(str);
out.flush();
}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);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
Simply put, the problem is you are intercepting the byte array of an unknown length and attempting to store them in array the size of one. Furthermore, it is ideal to append the packet size prior to the data in the packet and perhaps create the intercept in a separate thread waiting for incoming packets.
To just fix your ONCLICK2 you should do the following:
byte[] data = new byte[6556];
try {
in = socket.getInputStream();
// NOTE: The data byte array will contain empty values if
// under the size of 6556
int size = in.read(data);
// send to LogCat
Log.e("String", data.toString());
} catch (Exception e) {
e.printStackTrace();
}
I have not tested this code, but this should fix your problem.
I'm trying to write an Android client and a Java server.
It works to send a message from the Android client to the server (if the testing code is commented out), but I cannot get the response back from the server to the client.
Could you please help me?
Here's the client:
public class MainActivity extends Activity {
private PrintWriter printwriter;
private EditText textField;
private TextView textView;
private Button button;
private String message;
private String serverResponse;
String fromServer;
Socket clientSocket;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textField = (EditText) findViewById(R.id.editText1);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button1);
final String hostName = "10.111.207.253";
final int portNumber = 4444;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
message = textField.getText().toString();
textField.setText("");
new Thread(new Runnable() {
public void run() {
try {
clientSocket = new Socket(hostName, portNumber);
printwriter = new PrintWriter(clientSocket.getOutputStream(),true);
printwriter.write(message);
// testing only - trying to get the response back from the server
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(true) {
if ((serverResponse = in.readLine()) != null) {
Log.i("server says", serverResponse);
break;
}
}
// testing only
printwriter.flush();
printwriter.close();
clientSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
textView.setText("Server: " + serverResponse);
}
});
}
}
And here's the server:
public class MyServer {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept(); //accept the client connection
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
if (message != null) {
System.out.println("Client says: " + message);
//testing only
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
out.println("response from server");
//testing only
inputStreamReader.close();
clientSocket.close();
}
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
}
}
Please help!
You've inserted code to read a reply from the server before you flush your client's PrintWriter. You're not using println() so the boolean you passed to the constructor to enable autoflush doesn't apply as stated in the javadoc:
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output. These methods use the platform's own notion of line separator rather than the newline character.
This means the client is never sending anything, therefore the server never receives anything. Back in the client you'll block forever waiting for a reply that is never coming.
Either use printwriter.println() to send your message, or move printwriter.flush() to before you attempt to read a reply from the server.
I want to transfer data from Android device to the java desktop server. I have a text and button. As I press the button on the device, the text should be displayed on the java desktop server. I also have added AsyncTask in the client. The error code has also been added. The port i have used is 4444 and the ip address I used is of my local host address.
I am doing a very silly mistake. Can you please guide me.
I run the server code, it first gives me : Server started. Listening to the port 4444.
Now, I run the client code and write something on my mobile. As I press my button, it gives me error. And the app crashes and closes. I am a new one. Thanks in advance.
Client Code :
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textField = (EditText) findViewById(R.id.editText1); //reference to the text field
button = (Button) findViewById(R.id.button1); //reference to the send button
//Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
messsage = textField.getText().toString(); //get the text message on the text field
textField.setText(""); //Reset the text field to blank
try {
client = new Socket("134.190.162.165", 4444); //connect to server
printwriter = new PrintWriter(client.getOutputStream(),true);
printwriter.write(messsage); //write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); //closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public class Asynctask extends AsyncTask<View, Integer, Socket>
{
private static final String IP_ADDRESS = "134.190.162.165"; // Toshiba laptop
// private static final String IP_ADDRESS = "10.0.0.2"; // Toshiba laptop
private static final int DEST_PORT = 4444;
private EditText mTextField;
/**
* Store provided views (used later in onPostExecute(...)).
*
* Create socket to communicate with server (blocking call).
*/
protected Socket doInBackground(View... params)
{
// Store provided views.
if (params.length != 1)
throw new IllegalArgumentException();
mTextField = (EditText) params[0];
// Create socket.
Socket client = null;
try
{
client = new Socket(IP_ADDRESS, DEST_PORT); // connect to server
} catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return client;
}
/**
* Write to server.
*/
protected void onPostExecute(Socket client)
{
try
{
PrintWriter printwriter;
String messsage;
messsage = mTextField.getText().toString(); // get the text message on the text field
mTextField.setText(""); // Reset the text field to blank
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(messsage); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
Server Code:
public class server {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(4444); //Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept(); //accept the client connection
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
System.out.println(message);
inputStreamReader.close();
clientSocket.close();
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
}
}
}
The error which I get is:
FATAL EXCEPTION: main
android.os.NetworkOnMainThreadException
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
libcore.io.IoBridge.connectErrno(IoBridge.java:127)
libcore.io.IoBridge.connect(IoBridge.java:112)
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
java.net.Socket.startupSocket(Socket.java:572)
java.net.Socket.tryAllAddresses(Socket.java:127)
java.net.Socket.<init>(Socket.java:177)
java.net.Socket.<init>(Socket.java:149)
com.example.client.MainActivity$1.onClick(MainActivity.java:42)
android.view.View.performClick(View.java:3567)
In the manifest file, I have added all the requirements. It does not give any compile time error.
I checked from many websites but the code which is working is this only. But I dont know where I am making mistake in running it or somewhere else.
If any other option is there, please suggest me, i am scratching my head since long
Thanks
Your code seems very confusing. The client seems to have code for doing the network connection and I/O both on the main thread (in the OnClickListener attached to button) and in the AsyncTask (which is never created). Try this for an OnClickListener:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
message = textField.getText().toString(); //get the text message on the text field
textField.setText(""); //Reset the text field to blank
new Asynctask().execute(message);
}
});
But you have another problem: while your AsyncTask is (correctly) making the socket connection in doInBackground, it is incorrectly doing the network I/O in onPostExecute. The network I/O also needs to be done in the background. Try this for an AsyncTask:
public class Asynctask extends AsyncTask<String, Void, Void> {
private static final String IP_ADDRESS = "134.190.162.165"; // Toshiba laptop
// private static final String IP_ADDRESS = "10.0.0.2"; // Toshiba laptop
private static final int DEST_PORT = 4444;
private EditText mTextField;
/**
* Store provided views (used later in onPostExecute(...)).
*
* Create socket to communicate with server (blocking call).
*/
protected Void doInBackground(String... messages) {
if (messages.length != 1) { return null; }
String message = messages[0];
// Create socket.
Socket client = null;
try {
client = new Socket(IP_ADDRESS, DEST_PORT); // connect to server
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Write to server.
try {
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(messsage); // write the message to output stream
printwriter.flush();
printwriter.close();
}
catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The above is entirely untested, so it may not be exactly right. I also didn't look at your server code; this answer just addresses the NetworkOnMainThreadException problem.
So, i have a Android-App(Client) and a Java-program(Server), with a One-time socket communication, whenever the android app connects to my server in a special activity (working fine).
Because my server is embedded in a bigger program (with Swing-components, where the server takes its informations from), i have this (reduced) code here:
//somewhere in my Swing-Application
Server myServer = new Server();
myServer.start();
//...
public class Server extends Thread {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8090);
try {
while (true) {
System.out.println("Server is waiting for connections...");
socket = serverSocket.accept();
startHandler(socket);
}
} finally {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void startHandler(final Socket socket) throws IOException {
System.out.println("Client connected to Server");
Thread thread = new Thread() {
#Override
public void run() {
try {
writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
//doing something usefull, i am sending a JSON-String, which i´ll parse in my app.
writer.write(someStringContainingJSONString);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeSocket();
}
}
private void closeSocket() {
try {
socket.close();
} catch (IOException e) {
}
}
};
thread.start();
}
In my Android-App i have:
public void onCreate(Bundle savedInstanceState) {
viewJSON = new Runnable() {
#Override
public void run() {
getJSON();
}
};
Thread thread = new Thread(null, viewJSON, "MagentoBackground");
thread.start();
myProgressDialog = ProgressDialog.show(myActivity.this, "Please wait...", "Retrieving data ...", true);
}
private void getJSON() {
try {
socket = new Socket(serverIPAddress, SERVER_PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String help = reader.readLine();
// parse this String according to JSON, is working fine!
}
// catch and so on...
Now, i want the app, to recieve data, whenever i hit a button "send data" from my Swing-Application, to have the newest data available.
On the other hand, i want the server to recieve data (also a JSON-String) when i make changes in my Android app. The String should also be send when i hit a specific button.
How can i do that? The problem is the threading issue(otherwise my swing application wouldn´t work) combined with networking. If i don´t close the socket, i cannot continue with my program properly (or at least, it seems so with my code right now)
Can you help me out here?
Thank you very much in advance for your help and thoughts.
Best, Andrea