Android socket client not receiving from java server - android

My app is sending data to the java socket server but it is only displaying the first message it receives from the server and not the other messages.
The Server is multi threaded.
I have created two clients in java both are sending and receiving messages through the server but in android app I am having problem receiving data.
This is the complete code of the Android client.
public class MainActivity extends AppCompatActivity {
Socket client;
EditText writeMsg;
TextView displayMsg;
String userInput;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
writeMsg = (EditText) findViewById(R.id.editText1);
displayMsg = (TextView) findViewById(R.id.textView);
ReceiveMsg obj = new ReceiveMsg();
Thread tr = new Thread(obj);
tr.start();
}
// A button to send msg to server when clicked
public void sendBtn(View view){
userInput = writeMsg.getText().toString();
SendMessage object = new SendMessage();
object.execute();
}
private class SendMessage extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
client = new Socket("10.0.2.2", 4444);
PrintWriter output = new PrintWriter(client.getOutputStream(), true);
output.print(userInput);
output.flush();
output.close();
client.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
class ReceiveMsg implements Runnable {
public void run() {
try {
client = new Socket("10.0.2.2", 4444);
BufferedReader in =
new BufferedReader(
new InputStreamReader(client.getInputStream()));
int i = 0;
while (i == 0) {
displayMsg.setText(in.readLine());
}
} catch (Exception e) {
}
}
}
}
I want the app to display the newly received message in the text-view and overwrite the existing message.

You create two client sockets. One for sending and one for receiving.
Normal would be only one client socket who sends a command and then receives the reply of the server.

As usual, you are reading lines, but you aren't sending lines.
Use println(), not print().
You also need to stop reading when you get an IOException, or when readLine() returns null.
Why there are two client sockets is another mystery.

Related

Using AsyncTask to send a single UDP packet

I am running a python server in my computer that is looping forever and waits for data to be received and when it receives the data, it turns on\off the lights in my room.
In order to control it nicely I created an app that sends UDP packets to the server when I press a button to toggle the lights. My code is:
public class MainActivity extends AppCompatActivity {
private TextView txtView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = findViewById(R.id.status);
new Client(this).execute("init");
}
public void toggle(View view) {
new Client(this).execute("toggle");
}
private static class Client extends AsyncTask<String, String, String> {
DatagramSocket clientSocket;
String address = "192.168.1.243";
int port = 6789;
private WeakReference<MainActivity> activityReference;
Client(MainActivity context) {
activityReference = new WeakReference<>(context);
}
#Override
protected String doInBackground(String... strings) {
try {
clientSocket = new DatagramSocket();
byte[] sendData = strings[0].getBytes();
publishProgress("waiting for data");
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName(address), port);
clientSocket.send(sendPacket);
if (strings[0].equals("init")) {
// Receive result
DatagramSocket serverSocket = new DatagramSocket(6789);
byte[] receiveData = new byte[0];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
publishProgress(new String(receivePacket.getData(), 0, receivePacket.getLength()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (clientSocket != null)
clientSocket.close();
}
return address;
}
#Override
protected void onProgressUpdate(String... strings) {
super.onProgressUpdate(strings);
activityReference.get().txtView.setText(strings[0]);
}
}
}
However, this way, I create a AsyncTask every time I press the button, I wanted to know if it is a good practice or there is a better way to achieve this.
Thanks.
Yes, it's perfectly fine to create a new instance of the AsyncTask. You can not re-run it anyways.

Android Socket client unable to send and receive messages

I want to send and receive messages from my socket server which is created in python on windows with the help of twisted API. My client is going to be my android phone through I am going send my string messages. Here is my code. can someone please help out.
public class MainActivity extends AppCompatActivity
{
//TextView textView;
Button sendButton;
Button connect;
EditText message;
OutputStream outputStream;
InputStream inputStream;
Socket socket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendButton = (Button) findViewById(R.id.sendButton);
connect = (Button) findViewById(R.id.button);
message = (EditText) findViewById(R.id.message);
connect.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
connect.setText("Disconnect");
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects)
{
try {
socket = new Socket("192.168.100.106",8888);
try {
outputStream = socket.getOutputStream();
inputStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
connect.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
sendButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view)
{
PrintWriter out = new PrintWriter(outputStream);
String mes = message.getText().toString();
out.print(mes);
}
});
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
asyncTask.execute();
}
});
}
}
And here is my socket server script coded in python with the help of twisted API.
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
import ctypes # An included library with Python install.
class DataTransfer(Protocol):
def connectionMade(self):
#self.transport.write("""connected""")
self.factory.clients.append(self)
print "clients are ", self.factory.clients
self.username = ""
self.password = ""
self.auth = False
self.ipaddress = self.transport.getPeer()
print self.ipaddress
def connectionLost(self, reason):
self.factory.clients.remove(self)
print reason
def dataReceived(self, data):
print data
a = data.split(':')
if len(a) > 1:
command = a[0]
content = a[1]
msg = ""
self.message(msg)
def message(self, message):
self.transport.write(message + '\n')
factory = Factory()
factory.protocol = DataTransfer
factory.clients = []
reactor.listenTCP(8888, factory)
print "Server started"
reactor.run()
Presently I am able to communicate (ie. connect and disconnect with the server.) but its just that I am not able to send and receive messages.
Instead of PrintWriter out = new PrintWriter(outputStream); directly use the outputStream and it should work. :)

How to get connection with ServerSocket?

I want to develop app that connect to a server and send and receive message. i'm really beginner in that.
So,i wrote this code by This tutorial, and it seem that i get some mistake with the port or ip address beacuse i didn't get the message to the console. My inspiration is the problem is in my router setting maybe
Here is my android code (Project android)
public class MainActivity extends Activity {
Socket client;
PrintWriter printWriter;
EditText edIp,edPort,edMess;
String message;
int port = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edIp = (EditText) findViewById(R.id.edIp);
edPort = (EditText) findViewById(R.id.edPort);
edMess= (EditText) findViewById(R.id.edMessage);
edIp.setText("10.0.2.2");
edPort.setText("4444");
}
public void onClick(View v){
message = edMess.getText().toString();
edMess.setText("");
port = Integer.parseInt(edPort.getText().toString());
new Thread(new Runnable() {
#Override
public void run() {
try {
client = new Socket(edIp.getText().toString(),port);
printWriter = new PrintWriter(client.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}).start();
}
}
(java aplication)
public class Main {
public static void main(String[] args) throws IOException {
Socket clientSocket = null;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
System.out.println("Server started...");
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("error" + e);
}
Scanner in1 = new Scanner(clientSocket.getInputStream());
String mess;
while (true) {
if(in1.hasNext()){
mess = in1.nextLine();
System.out.println("Client message : "+mess);
}
}
}
}

Android networking does not work in emulator

I am working on a basic client-server application to send messages between an android app (client) and a java server on the pc. The messages are being sent and received fine when I use the emulator but does not work when i try to use the app on my mobile. I connect my phone to a wifi network hosted by my laptop using connectify. I wonder whats preventing my phone from connecting...
Here is the code :
SERVER
public class ServerMain {
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
int sock = 1234;
ServerSocket welcomeSocket = new ServerSocket(sock);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
if(clientSentence.equalsIgnoreCase("QUIT"))
break;
}
welcomeSocket.close();
}
}
CLIENT
public class Message extends Activity {
EditText et;
String msg1 = "";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
et = (EditText)findViewById(R.id.etTest);
}
// TODO Auto-generated method stub
class GetMessages extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
final String msg = et.getText().toString();
try{
Socket clientSocket = new Socket("*myip*", 1234);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
String sentence = msg;
outToServer.writeBytes(sentence + '\n');
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public void readWebpage(View view) { //The button on click calls this function (from xml)
new GetMessages().execute();
}
}

Send input to all clients SocketServer Android

I am trying to make a Server that sends back to all connected clients any input it has received. I am using a Service that on create it starts a thread.
public void onCreate()
{
Thread fst = new Thread(new ServerThread());
fst.start();
}
Here is the Thread
public void run()
{
try
{
serverSocket = new ServerSocket(SERVERPORT);
while (true)
{
// listen for incoming clients
Socket client = serverSocket.accept();
mclients = new Vector<Socket>();
mclients.add(client);
boolean finished = false;
try
{
for(int i=0; i<mclients.size(); i++) {
DataInputStream in = new DataInputStream(mclients.get(i).getInputStream());
PrintStream out = new PrintStream(mclients.get(i).getOutputStream());
// Print a message:
System.out.println("Client from : " + mclients.get(i).getInetAddress() + " port " + mclients.get(i).getPort());
// now get the input from the socket...
while(!finished)
{
String st = in.readLine();
// Send the same back to client
out.println(st);
// Write it to the screen as well
System.out.println(st);
// If the input was "quit" then exit...
if (st.equals("quit")) { finished = true; System.out.println("Thread exiting..."); }
}
}
handler.post(new Runnable() {#Override public void run() {}});
}
catch (final Exception e) {handler.post(new Runnable() {#Override public void run() {}});e.printStackTrace();}
}
It works only for the client who sent the input. The input is not echoed back to all clients.Can anyone help me out with this.I think that my client code is wrong but i can't figured it out.Here is my client code:
public class Client extends Activity implements OnClickListener{
private EditText serverIp;
private static EditText data;
private TextView receivedata, answer1 ,answer2, answer3, answer4;
private Button connectPhones, send;
private String serverIpAddress = "";
private boolean connected = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client);
serverIp = (EditText) findViewById(R.id.server_ip);
receivedata = (TextView) findViewById(R.id.textView1);
answer1 = (TextView) findViewById(R.id.txtans1);
answer2 = (TextView) findViewById(R.id.txtans2);
answer3 = (TextView) findViewById(R.id.txtans3);
answer4 = (TextView) findViewById(R.id.txtans4);
data = (EditText) findViewById(R.id.data);
connectPhones = (Button) findViewById(R.id.connect_phones);
send = (Button) findViewById(R.id.send);
connectPhones.setOnClickListener(this);
send.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v == send)
{
if (!connected)
{
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals(""))
{
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
}
public class ClientThread implements Runnable
{
String line;
String[] answers = new String[5];
final Handler handler = new Handler();
final Runnable updateUI = new Runnable() {
public void run() {
receivedata.setText( line );
//answer1.setText( answers[1] );
//answer2.setText( answers[2] );
//answer3.setText( answers[3] );
//answer4.setText( answers[4] );
}
};
public void run()
{
try
{
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: SENDING...");
Socket socket = new Socket(serverAddr, 5000);
connected = true;
while(connected)
{
try
{
BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
out.println(data.getText());
line = in.readLine(); // read server
System.out.println("Echo: " + line);
handler.post(updateUI);
in.close(); // Close stream
out.close();
}
catch (Exception e)
{
Log.e("ClientActivity", "S: Error", e);
}
connected = false;
}
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e)
{
Log.e("ClientActivity", "C: Error", e);
}
}
}}
-----EDIT------
Should i use a different thread for handling the clients or it would be a problem? And how should i do that?
I see that you are also instantiating ServerSocket itself within the loop.
you dont need to create a new serversocket for each connection, you only need one server socket then loop to accept connections and add connections to the (already instantiated in oncreate()) list. see the example below.
if this still doesn't work then we'll have to see rest of the code aswell.
And i like to stress again on that this will not always work on android, as android can also kill your service and app to grab resources, and everytime wifi, 3g or whatever is on the phone looses connection your socket is likely to fail.
ArrayList<Socket> mCLients;
ServerSocket serverSocket;
public void onCreate()
{
mCLients; = new ArrayList<Socke>();
serverSocket = new ServerSocket(SERVERPORT);
Thread fst = new Thread(new ServerThread());
fst.start();
}
//.....
private Static void send(final String message){
Thread thread = new Thread(){
for(Socket socket: mClients){
// send message to the socket
}
}
thread.start();
}
//....
public void run(){
while (true)
{
// listen for incoming clients
Socket client = serverSocket.accept();
mclients.add(client);
//Read client input
MyService.send(message);
}
}
Note this code is no way the best way, i am just giving you a quick example on how you should approach this.
By having a quick (very quick) look i believe your problem seems to be the following code inside the run()
mclients = new Vector();
you are creating a new vector object every-time your program runs.
i suggest to move this out of the run(), and make sure your mClients is created before you start the thread that listens for incoming connections.
However note: running server on the android phone is a bad idea! mobile phones have limitations such as limited battery life, processing, memory and inconsistent internet connectivity, there are other ways to handle such communication. for example consider messaging, c2dm, xmpp etc.

Categories

Resources