I have established a connection between java server and android client using sockets. I can send messages from android to java, but only 1 message at a time.
what if I want to send data of 2 variables from android to java and at the same time receive those data in java in 2 different variables.
How can I achieve this.??
Code for Android Client
public class MessageClient extends Activity implements OnClickListener {
EditText etMessage;
Button bSend;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.messageclient);
bSend = (Button) findViewById(R.id.button1);
etMessage = (EditText) findViewById(R.id.etMessage);
bSend.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
try {
Socket s = new Socket("192.168.0.100",7000);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(etMessage.getText().toString());
dos.flush();
dos.close();
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Code for java server
public static void main(String arg[]){
Thread t = new Thread(){
public void run() {
// TODO Auto-generated method stub
try {
ServerSocket ss = new ServerSocket(7000);
while(true){
Socket s = ss.accept();
System.out.println("Server is running");
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println("Received from client: "+dis.readUTF());
dis.close();
s.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
}
Thank you.
You are just sending a String and then closing the socket.You can try to send lists and also can send multiple DataInputStream dis without closing the socket connection.
Related
I am trying to create a connection between two applications using android. I have tried to use sockets to connect. I have created two application
One which accepts the connection when client wants to connect
and another application that requests to connect.
I have successfully run this code in same manner in pc in java in pc network. Is the way of connecting to android also same?
My server class implementation
public class MainActivity extends AppCompatActivity {
private Button startButton;
private ServerSocket server;
private Socket connection;
private TextView statusText;
private ObjectOutputStream output;
private ObjectInputStream input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusText=(TextView)findViewById(R.id.statusText);
startButton=(Button)findViewById(R.id.startButton);
startButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
startRunning();
}
}
);
}
private void startRunning() {
try{
server=new ServerSocket(8080);
while(true)
{
try{
waitForConnection();
setUpStreams();
whileChatting();
}catch(Exception e){}
}
} catch(Exception e){}
}
public void waitForConnection()
{
setMyStatus("Waiting for client to connect...");
try {
connection= server.accept();
setMyStatus("Now connected to "+ connection.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpStreams()
{
try {
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
setMyStatus("Streams are now setup. Ready to go...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void whileChatting()
{
setMyStatus("You can now start chatting...");
}
public void setMyStatus(String msg) {
statusText.setText(msg);
}
}
I will use the tasks like async task later. But i am just trying to set up connection in these application.
My client implementation goes like this
public class MainActivity extends AppCompatActivity {
private Button startButton;
private Socket connection;
private TextView statusText;
public ObjectOutputStream output;
public ObjectInputStream input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusText=(TextView)findViewById(R.id.statusText);
startButton=(Button)findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startRunning();
}
});
}
private void startRunning() {
connectToServer();
setUpStreams();
whileChatting();
}
public void connectToServer()
{
setMyStatus("Connecting to server. Please wait...");
try {
connection= new Socket(InetAddress.getByName("127.0.0.1"),8080);
setMyStatus("Connected to Server."+ connection.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpStreams()
{
try {
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
setMyStatus("Streams are now setup. Ready to go...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void whileChatting()
{
setMyStatus("You can now start chatting...");
}
public void setMyStatus(String msg) {
statusText.setText(msg);
}
}
The error I got is in the case of client that tries to connect to server
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.OutputStream java.net.Socket.getOutputStream()' on a null object reference
at com.myapp.client.clientdemo.MainActivity.setUpStreams(MainActivity.java:71)
at com.myapp.client.clientdemo.MainActivity.startRunning(MainActivity.java:46)
at com.myapp.client.clientdemo.MainActivity.access$000(MainActivity.java:16)
at com.myapp.client.clientdemo.MainActivity$1.onClick(MainActivity.java:33)
It's because "connection" was never created. Probably because it failed to connect or it timed out and it moved on to the next code. If it timed out or didn't connect, then you need to catch that exception and retry to connect before moving on with your later code.
Socket can be tricky if you do not catch all the erroneous states they can get into.
simply wrap your try and catch with a while loop until the condition is met like this:
while(!connected & !closed){
try {
connection= new Socket(InetAddress.getByName("127.0.0.1"),8080);
connected = true;
//now it is connected and will exit the loop and continue with other code
} catch (SocketTimeoutException socketTimeoutException) {
//add this for safety
} catch (IOException e) {
e.printStackTrace();
}
}
I have a little C++/Java - Socket Server (UDP) running on my PC.
Now, i want to connect with my Android App to the Server. But when i send a package my App crash.
public void Socketinit() {
// 1. Socket erstellen!
try {
serverAddr = InetAddress.getByName("192.168.0.101");
socket = new DatagramSocket();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
createListeners();
}
and
entprivate void createListeners() {
confirm.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
buf = input.getText().toString().getBytes();
DatagramPacket packet = new DatagramPacket(buf,buf.length, serverAddr, SERVERPORT);
try {
socket.send(packet);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
It crashs on "socket.send(packet);"
I can connect to my Server via C++ so the Server is up and running. Where is the Clientproblem in my code ?
thanks
You are propably getting the NetworkOnMainThreadException (see Logcat or check in the debugger).
You can use an AsyncTask to resolve this.
Propably you are also missing the Internet permission in the manifest.
Here are further details: How to fix android.os.NetworkOnMainThreadException?
I'm new at developing at android OS. I try developing my telnet client for android OS.
Now, I only try to connect telnet server, and receive login message.
But when I start socket to connect telnet server Ihave received strange symbols ??????!???? instead the logon message from telnet server.
public class MainActivity extends Activity {
protected static final int TCP_SERVER_PORT = 23;
protected String inMsg, str;
static Editable sentence;
static String modifedSentence;
BufferedReader inFromUser;
Socket clientSocket = null;
DataOutputStream outToServer=null;
BufferedReader inFromServer=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button)findViewById(R.id.startButton);
final TextView textView = (TextView)findViewById(R.id.textView);
startButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
new Thread(new Runnable() {
#Override
public void run() {
//Create socket
try {
clientSocket = new Socket("192.168.1.1",23);
//Create out stream for ClientSocket
outToServer = new DataOutputStream(clientSocket.getOutputStream());
//Create ib stream for ClientSocket
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//Receive login message from telnet server
modifedSentence = inFromServer.readLine();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Update UI activity with login message
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(modifedSentence);
}
});
}
}).start();
}
});
}
protected void onDestroy()
{
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
These "strange" symbols ??????!???? mean, that you use wrong encoding. When you create InputStreamReader you should explicitly point which encoding this stream should use. I don't known which encoding is used inside your telnet service, but you can try various of them, e.g. windows-1252:
new InputStreamReader(clientSocket.getInputStream(), Charset.forName("windows-1252"))
Telnet app require telnet protocol for connections to the telnet server. It's not a simple tcp connection. I use apache commonse library which provide class for telnet accessing.
Thanks
I have got huge problem with my Android app and I would like to ask you for help.
I am currently writing Android Clietn-Server app using sockets. I have found lots of tutorils on the Internet and from them I have created basics for my project. However, all tutorials are only for one message send and that's all. I need to send more of them so I've been trying to modify it.
This are code fragments responsible for server and client. The rest is not important at this time.
Server:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverStatus = (TextView) findViewById(R.id.server_status);
recivedMsg = (TextView)findViewById(R.id.rec_msg);
SERVERIP = getLocalIpAddress();
Thread fst = new Thread(new ServerThread());
fst.start();
}
public class ServerThread implements Runnable {
public void run() {
try {
if (SERVERIP != null) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Listening on IP: " + SERVERIP);
}
});
serverSocket = new ServerSocket(SERVERPORT);
while (true) {
// listen for incoming clients
Socket client = serverSocket.accept();
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Connected." + System.getProperty("line.separator"));
}
});
try {
line = null;
while (connected) {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
if((line = in.readLine())!=null)
{
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
if(recivedMsg.equals("CLOSE"))
{
recivedMsg.append("CLOSE socket");
connected = false;
}
else
{
recivedMsg.append("MSG: " + line + System.getProperty("line.separator"));
}
// do whatever you want to the front end
// this is where you can be creative
}
});
}
else
{
recivedMsg.append("empty" + System.getProperty("line.separator"));
}
}
break;
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Oops. Connection interrupted. Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
} else {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Couldn't detect internet connection.");
}
});
}
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Error");
}
});
e.printStackTrace();
}
}
}
Client
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
sendField = (EditText) findViewById(R.id.send_field);
sendMsg = (Button) findViewById(R.id.msg_send);
connectPhones.setOnClickListener(connectListener);
sendMsg.setOnClickListener(sendMessage);
}
#Override
protected void onStop() {
super.onStop();
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "CLOSE";
out.write(outMsg);
out.flush();
// make sure you close the socket upon exiting
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private OnClickListener connectListener = new OnClickListener() {
#Override
public void onClick(View v) {
serverIpAddress = serverIp.getText().toString();
runTcpConnection();
sendMessageToServer("Msg");
}
};
private OnClickListener sendMessage = new OnClickListener() {
#Override
public void onClick(View v) {
sendMessageToServer(sendField.getText().toString());
}
};
private void runTcpConnection() {
try {
s = new Socket(serverIpAddress, SERVERPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "TCP connecting to " + SERVERPORT + System.getProperty("line.separator");
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
SystemClock.sleep(10);
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
};
public void sendMessageToServer(String str) {
try {
s = new Socket(serverIpAddress, SERVERPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = str + System.getProperty("line.separator");
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "hello222");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "hello4333");
}
}
For now devices connect correctly. Moreover They are sending the first connection messages (those in OnClickListener connectListener). The problem is that when I am trying to send another message using sendMessageToServer it is impossible. Those messages shows only after client activity is destroyed.
Very interesting is that without SystemClock.sleep(10); listener runTcpConnection() behave strange. Only 'Connected.' displays on server.
Can someone tell me what I have to do to be able to send messages normally?
EDIT:
This are things that I have found:
If I am at the connection sending more messages than all are empty (null) and after the second one connection error shows - please reconnect phones
If I am at the connection sending more messages without s.close line in sendMessageToServer only one message is passing through. No error is displayed after it.
The message form runTcpConnection shows always (except when in this function is no SystemClock.sleep(10))
Hope it will help someone to diagnose my error.
As I see, you create a new socket whenever user click button send, right? I recommend you should init it only one time when user click connect, then you use it in send click event ( because this is TCP, you will disconnect to server if you create new instance of socket)
So, you should remove these lines in sendMessageToServer :
s = new Socket(serverIpAddress, SERVERPORT);
s.close();
and this line in runTcpConnection
s.close();
Socket should close whenever you don't want communicate with the server (onstop is an example, or when change activity...)
Also you should create only one instance of BufferedWriter too.
Hope this help.
i got this code form Android-er blogspot, big thanks for him to make me almost understand basic socket connections in java. So i got this client app on my android device, and computer with server running, but how could i make a loop in a client code, to make it send data from EditText in real time? (whenever it changes) Please if someone could clear it out for a complete newbie?
-----This is client code (Android-er Copyrights):
package com.exercise.AndroidClient;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class AndroidClient extends Activity {
EditText textOut;
TextView textIn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textOut = (EditText)findViewById(R.id.textout);
Button buttonSend = (Button)findViewById(R.id.send);
textIn = (TextView)findViewById(R.id.textin);
buttonSend.setOnClickListener(buttonSendOnClickListener);
}
Button.OnClickListener buttonSendOnClickListener
= new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("192.168.1.101", 8888);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(textOut.getText().toString());
textIn.setText(dataInputStream.readUTF());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if (socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}};
}
-----This is server code (Android-er Copyrights):
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args){
ServerSocket serverSocket = null;
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
serverSocket = new ServerSocket(8888);
System.out.println("Listening :8888");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true){
try {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
System.out.println("message: " + dataInputStream.readUTF());
dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if( socket!= null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataInputStream!= null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataOutputStream!= null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
There are a few things you will need to change.
First of all, if you want the data to be sent in real time, you will need to change from using a Button OnClickListener to using a TextWatcher (see addTextChangedListener in TextView)
As this event will be fired every time the text changes, you will need to open your socket outside of the event (you don't want a new socket each time some text is typed), and then in your listener, you just want to send the new data down the socket.
You can set a text changed listener on your EditText and do the sending from there.
edittext.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
// ... do your sending here
}
But beware that if that sending is not asynchronous, it may block text entry for the user. Network latency can be relatively high on GSM networks, so the user may be irritated, when his freshly typed characters will not immediately appear on screen.