Following is "TCP SERVER" code, when any client connect first time the code is run very well, but once that client disconnect and again connect with TCP SERVER, than client connects successfully but can not send data.
How to detect client is disconnected with server?
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
public class MainActivity extends AppCompatActivity {
TextView tvStatus;
EditText etPort, etMsg, etTransmit;
Button btnListen, btnServerSend;
Handler UIHandler;
private int SERVERPORT1;
private InetAddress addr;
private ServerSocket serverSocket;
private Socket clientSocket = null;
private BufferedReader in;
private PrintWriter out;
// public static final int SERVERPORT = 3000;
private WifiManager wifiManager = null;
private WifiManager.WifiLock lock = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wifi();
UIHandler = new Handler();
tvStatus = (TextView) findViewById(R.id.tvStatus);
etMsg = (EditText) findViewById(R.id.etMsg);
etTransmit = (EditText) findViewById(R.id.etTransmit);
etPort = (EditText) findViewById(R.id.etPort);
btnListen = (Button) findViewById(R.id.btnListen);
btnServerSend = (Button) findViewById(R.id.btnServerSend);
// ******************* Register controls end ******************************
btnListen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new ServerClass().execute(etPort.getText().toString());
}
});
}
public String getLocalIpAddress() throws Exception {
String resultIpv6 = "";
String resultIpv4 = "";
for (Enumeration en = NetworkInterface.getNetworkInterfaces();
en.hasMoreElements(); ) {
NetworkInterface intf = (NetworkInterface) en.nextElement();
for (Enumeration enumIpAddr = intf.getInetAddresses();
enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = (InetAddress) enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
if (inetAddress instanceof Inet4Address) {
resultIpv4 = inetAddress.getHostAddress().toString();
} else if (inetAddress instanceof Inet6Address) {
resultIpv6 = inetAddress.getHostAddress().toString();
}
}
}
}
return ((resultIpv4.length() > 0) ? resultIpv4 : resultIpv6);
}
private class ServerClass extends AsyncTask<String, Object, String> {
private String input;
#Override
protected String doInBackground(String... params) {
try {
SERVERPORT1 = Integer.parseInt(params[0]);
addr = InetAddress.getByName(getLocalIpAddress());
serverSocket = new ServerSocket(SERVERPORT1, 0, addr);
while (true) {
clientSocket = serverSocket.accept();
clientSocket.setTcpNoDelay(true);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
tvStatus.setText(clientSocket.getInetAddress().toString() + " Client connected");
Toast.makeText(MainActivity.this, "Server started...", Toast.LENGTH_SHORT).show();
}
});
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
if (!Thread.currentThread().isInterrupted()) {
input = in.readLine();
if (input != null) {
UIHandler.post(new updateUIThread1(input.toString()));
out.println("Received from client: " + input);
} else {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
new ServerClass().execute(etPort.getText().toString());
}
});
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
private class updateUIThread1 implements Runnable {
private String input = null;
public updateUIThread1(String input) {
this.input = input;
}
#Override
public void run() {
if (input.getBytes().length != 0) {
etMsg.append("\n" + input.toString());
Toast.makeText(MainActivity.this, "Answer: " + input, Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "Empty", Toast.LENGTH_SHORT).show();
}
}
}
}
Log shows like:
04-22 12:57:05.799 10857-10931/com.chat.admin.clientserver I/System.out: [CDS]shutdownInput in read
04-22 12:57:05.799 10857-10931/com.chat.admin.clientserver I/System.out: [CDS]shutdownInput in read
04-22 12:57:05.799 10857-10931/com.chat.admin.clientserver I/System.out: [CDS]shutdownInput in read
04-22 12:57:05.799 10857-10931/com.chat.admin.clientserver I/System.out: [CDS]shutdownInput in read
04-22 12:57:05.799 10857-10931/com.chat.admin.clientserver I/System.out: [CDS]shutdownInput in read
read: unexpected EOF!
Do not create a new server if a client disconnects.
Instead you should have a loop so you can call .accept() again to wait for a new client.
Related
EDIT: My solution was to have a constant class with this code:
static EditText Port = (EditText) MainActivity.mDialog.findViewById(R.id.txtPort); static int mPort = Integer.parseInt(Port.getText().toString()); public static final int PORT = mPort;
I've tried to see the other questions and I understand that I've gotta do something with the UIThread? Honestly, I understand nothing. Im new with android.
The app (chat app) worked fine until I wanted to have multiple ports options depending if I'm hosting (port 5050) or joining (port 80) a chat room. From the beginning i just had a constant value of the port (public static final int PORT) but now i cant have that ofc. If you guys have any other suggestions on how i can have two values of PORT, please share your tips.
Anyway, after trying EVERYTHING I decided to put a method in my main class, and just declare it in other classes. This is the mothod for the value of the port:
public int getPORT() {
txtPORT = (EditText) findViewById(R.id.txtPort);
//String txtPORTa = txtPORT.getText().toString();
int dennaPORT = 0;
if (mJoin.isChecked()) {
dennaPORT = Integer.parseInt(txtPORT.getText().toString());
return dennaPORT;
}
else if (mHost.isChecked()) {
dennaPORT = 5050;
return dennaPORT;
}
return dennaPORT;
}
This is my MainActivity
package chat.chris.android.se.chatup;
import android.app.Activity;
import android.app.Dialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import java.util.ArrayList;
import chat.chris.android.se.chatup.Listeners.ChatListener;
import chat.chris.android.se.chatup.Listeners.ConnectionListener;
import chat.chris.android.se.chatup.Networking.Client;
import chat.chris.android.se.chatup.Networking.Server;
import chat.chris.android.se.chatup.Utilities.ServerUtils;
import static chat.chris.android.se.chatup.R.id.rdioHost;
import static chat.chris.android.se.chatup.R.id.rdioJoin;
public class MainActivity extends Activity {
private Adapter chatAdapter;
private Button btnSendMessage;
private EditText txtMessage;
private ListView lstMessages;
private static Dialog mDialog;
private Client mClient;
private Server mServer;
private EditText txtPORT;
private RadioButton mJoin;
private RadioButton mHost;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showChatSelection();
chatAdapter = new Adapter(this, new ArrayList<ChatItem>());
lstMessages = (ListView) findViewById(R.id.lstChat);
lstMessages.setAdapter(chatAdapter);
txtMessage = (EditText) findViewById(R.id.txtSay);
txtMessage.setOnEditorActionListener(txtMessageEditorActionListener);
btnSendMessage = (Button) findViewById(R.id.btnSend);
btnSendMessage.setOnClickListener(btnSendMessageClickListener);
Client.setOnChatListener(chatListener);
Client.setOnConnectionListener(connectionListener);
}
public void showChatSelection() {
mDialog = new Dialog(this);
mDialog.setContentView(R.layout.layout_chat_choose);
mDialog.setTitle("Chat Room");
mDialog.setCancelable(false);
final EditText txtServer = (EditText) mDialog.findViewById(R.id.txtAddress);
final TextView lblServer = (TextView) mDialog.findViewById(R.id.lblAddress);
final TextView txtPort = (EditText) mDialog.findViewById(R.id.txtPort);
final RadioButton mHost = (RadioButton) mDialog.findViewById(rdioHost);
final RadioButton mJoin = (RadioButton) mDialog.findViewById(rdioJoin);
try {
lblServer.setText(ServerUtils.getLocalIp(this));
} catch (NullPointerException e) {
mHost.setEnabled(false);
mHost.setChecked(false);
lblServer.setText("Wifi must be enabled to host");
mJoin.setChecked(true);
txtServer.setVisibility(View.VISIBLE);
txtPort.setVisibility(View.VISIBLE);
}
mDialog.findViewById(R.id.btnChoose).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mDialog.findViewById(R.id.progLoading).setVisibility(View.VISIBLE);
new SetupChat().execute(mHost.isChecked(), mJoin.isChecked() ? txtServer.getText().toString() : "");
}
});
mHost.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mJoin.setChecked(false);
txtServer.setVisibility(View.INVISIBLE);
txtPort.setVisibility(View.INVISIBLE);
lblServer.setVisibility(View.VISIBLE);
}
}
});
mJoin.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mHost.setChecked(false);
txtServer.setVisibility(View.VISIBLE);
txtPort.setVisibility(View.VISIBLE);
lblServer.setVisibility(View.INVISIBLE);
}
}
});
mDialog.show();
}
private final OnClickListener btnSendMessageClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
sendMessage();
}
};
private final OnEditorActionListener txtMessageEditorActionListener = new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int id, KeyEvent event) {
if (id == EditorInfo.IME_ACTION_NEXT || id == EditorInfo.IME_ACTION_DONE)
sendMessage();
return true;
}
};
private final ChatListener chatListener = new ChatListener() {
#Override
public void onChat(String message) {
chatAdapter.addItem(new ChatItem("<html>" + message + "</html>", "Friend"));
}
};
private final ConnectionListener connectionListener = new ConnectionListener() {
#Override
public void onDisconnect(Client client) {
chatAdapter.addItem(new ChatItem(client.getName() + " left the chat room", ""));
}
#Override
public void onJoin(Client client) {
chatAdapter.addItem(new ChatItem(client.getName() + " joined the chat room", ""));
}
};
public void sendMessage() {
String message = txtMessage.getText().toString();
if(message == null || message.isEmpty())
return;
message = message.replace(">", ">");
message = message.replace("<", "<");
try {
if (mServer != null) {
mServer.sendMessage(message);
chatAdapter.addItem(new ChatItem(message, "You"));
} else if (mClient != null) {
mClient.sendMessage(message);
chatAdapter.addItem(new ChatItem(message, "You"));
} else {
return;
}
} catch (Exception e) {
chatAdapter.addItem(new ChatItem(e.getMessage(), "<font color='red'>Error</font>"));
return;
}
txtMessage.setText("");
}
public int getPORT() {
txtPORT = (EditText) findViewById(R.id.txtPort);
//String txtPORTa = txtPORT.getText().toString();
int dennaPORT = 0;
if (mJoin.isChecked()) {
dennaPORT = Integer.parseInt(txtPORT.getText().toString());
return dennaPORT;
}
else if (mHost.isChecked()) {
dennaPORT = 5050;
return dennaPORT;
}
return dennaPORT;
}
private class SetupChat extends AsyncTask<Object,Void, Boolean> {
#Override
protected Boolean doInBackground(Object... args) {
try {
if ((Boolean)args[0]) {
mServer = new Server();
new Thread(mServer).start();
} else {
String address = args[1].toString();
mClient = Client.connect(address);
if (mClient == null)
return true;
new Thread(mClient).start();
}
} catch (Exception e) {
e.printStackTrace();
return true;
}
return false;
}
#Override
protected void onPostExecute(Boolean errors) {
if (errors)
Toast.makeText(getApplicationContext(), "Någonting gick fel\nSkrev du in allting rätt?", Toast.LENGTH_LONG).show();
else
mDialog.dismiss();
}
}
}
This is the client class
package chat.chris.android.se.chatup.Networking;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import chat.chris.android.se.chatup.Listeners.ChatListener;
import chat.chris.android.se.chatup.Listeners.ConnectionListener;
import chat.chris.android.se.chatup.MainActivity;
import chat.chris.android.se.chatup.Utilities.Crypto;
public class Client implements Runnable {
private BufferedReader reader;
private DataOutputStream writer;
private boolean disconnecting;
private byte[] cryptoKey;
private String name;
private static ChatListener chatListener;
private static ConnectionListener connectionListener;
//Instansierar ny klient
public Client(Socket s) throws IOException {
cryptoKey = new byte[16];
try {
reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
writer = new DataOutputStream(s.getOutputStream());
} catch (IOException e) {
disconnect();
return;
}
}
//Ger klienten ett namn
public String getName() {
return name;
}
//Sätter namnet
public void setName(String name) {
this.name = name;
}
public static void setOnChatListener(ChatListener listener) {
chatListener = listener;
}
public static void setOnConnectionListener(ConnectionListener listener) {
connectionListener = listener;
}
public BufferedReader getReader() {
return reader;
}
public byte[] getKey(){
return cryptoKey;
}
public void setKey(byte[] key) {
cryptoKey = key;
}
#Override
public void run() {
if (connectionListener != null) {
connectionListener.onJoin(this);
}
try {
while (!disconnecting) {
String read;
if ((read = reader.readLine()) != null) {
if (chatListener != null) {
chatListener.onChat(Crypto.decrypt(read, cryptoKey));
}
}
else{
return;
}
Thread.sleep(5);
}
} catch (IOException e) {
disconnect();
} catch (Exception e) {
e.printStackTrace();
disconnect();
}
}
//Connectar till adressen och returnerar klienten
public static Client connect(String address) throws IOException {
MainActivity porten = new MainActivity();
int PORT;
PORT = porten.getPORT();
InetAddress localAddress = InetAddress.getByName(address);
InetSocketAddress localSocketAddress = new InetSocketAddress(localAddress, PORT);
Socket socket = new Socket();
socket.connect(localSocketAddress, 5000);
Client client = new Client(socket);
socket.getInputStream().read(client.cryptoKey, 0, 16);
System.out.println("Client -> " + new String(client.cryptoKey));
return client;
}
public void sendMessage(String message) throws Exception {
if(message == null || message.isEmpty())
return;
writer.writeUTF(Crypto.encrypt(message, cryptoKey));
}
public void disconnect() {
if (connectionListener != null) {
connectionListener.onDisconnect(this);
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
reader = null;
writer = null;
}
}
And this is the server class
package chat.chris.android.se.chatup.Networking;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Random;
import chat.chris.android.se.chatup.MainActivity;
import static chat.chris.android.se.chatup.Utilities.Constants.MAX_USERS;
//import static chat.chris.android.se.chatup.Utilities.Constants.PORT;
public class Server implements Runnable {
private ArrayList<Client> clientList;
private ServerSocket mSocket;
private byte[] cryptoKey;
private boolean shuttingDown;
MainActivity porten = new MainActivity();
//Instansierar en ny server chatt
public Server() throws IOException {
int PORT = porten.getPORT();
mSocket = new ServerSocket(PORT);
clientList = new ArrayList<>();
Random mRand = new SecureRandom();
cryptoKey = new byte[16];
mRand.nextBytes(cryptoKey);
System.out.println("Server ->" + new String(cryptoKey));
}
public boolean isShuttingDown() {
return shuttingDown;
}
public void setShuttingDown(boolean shuttingDown) {
this.shuttingDown = shuttingDown;
}
#Override
public void run() {
while (!shuttingDown) {
Socket socket = null;
Client client;
try {
socket = this.mSocket.accept();
if (clientList.size() >= MAX_USERS) {
socket.close();
return;
}
socket.getOutputStream().write(cryptoKey);
client = new Client(socket);
client.setKey(cryptoKey);
new Thread(client).start();
clientList.add(client);
} catch (IOException e) {
e.printStackTrace();
try {
if (socket != null)
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
public void sendMessage(String message) throws Exception {
for (Client client : clientList) {
if (shuttingDown)
return;
client.sendMessage(message);
}
}
public void shutdown() {
shuttingDown = true;
try {
mSocket.close();
} catch (IOException e) {
} finally {
mSocket = null;
}
}
}
With this setup im getting these errors:
05-04 00:41:58.969 12319-12370/chat.chris.android.se.chatup W/System.err﹕ java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-04 00:41:58.970 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.Handler.<init>(Handler.java:200)
05-04 00:41:58.975 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.Handler.<init>(Handler.java:114)
05-04 00:41:58.975 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.app.Activity.<init>(Activity.java:793)
05-04 00:41:58.975 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.MainActivity.<init>(MainActivity.java:32)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.Networking.Server.<init>(Server.java:21)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.MainActivity$SetupChat.doInBackground(MainActivity.java:229)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.MainActivity$SetupChat.doInBackground(MainActivity.java:221)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:288)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
05-04 00:41:58.976 12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
NEVER create an instance of an Activity, Service, or ContentProvider yourself. Those are always created by the framework. Delete:
MainActivity porten = new MainActivity();
Pass the port into the strangely-named Server class by some other means, such as a constructor parameter or setter method.
I am trying out the WebSockets with Fallbacks transports for Android, Node.js and Atmosphere example. I get an the following error:
/home/mofa/NetBeansProjects/App/src/com/jullio/advisor/wAsyncChat.java:87: error: cannot access JsonParseException
return mapper.readValue(data, Message.class);
class file for org.codehaus.jackson.JsonParseException not found
/home/mofa/NetBeansProjects/App/src/com/jullio/advisor/wAsyncChat.java:68: error: cannot access ObjectCodec
return mapper.writeValueAsString(data);
class file for org.codehaus.jackson.ObjectCodec not found
Here is the androidchat code:
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.atmosphere.wasync.ClientFactory;
import org.atmosphere.wasync.Decoder;
import org.atmosphere.wasync.Encoder;
import org.atmosphere.wasync.Event;
import org.atmosphere.wasync.Function;
import org.atmosphere.wasync.Request;
import org.atmosphere.wasync.RequestBuilder;
import org.atmosphere.wasync.impl.AtmosphereClient;
import org.codehaus.jackson.map.ObjectMapper;
import java.io.IOException;
import java.util.Date;
public class wAsyncChat extends Activity {
private Button bt;
private TextView tv;
private String serverIpAddress = "http://10.0.2.2:8080";
private final static ObjectMapper mapper = new ObjectMapper();
private final Handler uiHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
setContentView(R.layout.main);
bt = (Button) findViewById(R.id.myButton);
tv = (TextView) findViewById(R.id.myTextView);
try {
AtmosphereClient client = ClientFactory.getDefault().newClient(AtmosphereClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(serverIpAddress + "/chat")
.trackMessageLength(true)
.encoder(new Encoder<Message, String>() {
#Override
public String encode(Message data) {
try {
return mapper.writeValueAsString(data);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
})
.decoder(new Decoder<String, Message>() {
#Override
public Message decode(Event type, String data) {
data = data.trim();
// Padding
if (data.length() == 0) {
return null;
}
if (type.equals(Event.MESSAGE)) {
try {
return mapper.readValue(data, Message.class);
} catch (IOException e) {
e.printStackTrace();
return null;
}
} else {
return null;
}
}
})
.transport(Request.TRANSPORT.WEBSOCKET);
final org.atmosphere.wasync.Socket socket = client.create();
socket.on("message", new Function<Message>() {
#Override
public void on(final Message t) {
uiHandler.post(new Runnable() {
#Override
public void run() {
Date d = new Date(t.getTime());
tv.append("Author " + t.getAuthor() + "# " + d.getHours() + ":" + d.getMinutes() + ": " + t.getMessage() + "\n");
}
});
}
}).on(new Function<Throwable>() {
#Override
public void on(Throwable t) {
tv.setText("ERROR 3: " + t.getMessage());
t.printStackTrace();
}
}).open(request.build());
bt.setOnClickListener(new OnClickListener() {
String name = null;
public void onClick(View v) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
if (name == null) {
name = str;
}
socket.fire(new Message(name, str));
et.setText("");
Log.d("Client", "Client sent message");
} catch (Throwable e) {
tv.setText("ERROR 3: " + e.getMessage());
e.printStackTrace();
}
}
});
} catch (Throwable e) {
tv.setText("Unable to connect: " + e.getMessage());
e.printStackTrace();
}
}
}
I have the library for nodeserver connection. You can use it from git
SocketIO socketio = new SocketIO() {
#Override
public void onConnect() {
}
#Override
public void onDisconnect() {
}
#Override
public void onMessage(String message) {
Log.d("===Server Answer====",message);
}
};
socketio.Connect("192.168.0.1", 9000);
after onConnect() send the message:
socketio.send("Your message to socket");
it work with latest socketIO, and use RFC 6455 websocket protocol
After an exhaustive search on the internet, I managed to assemble a code that sends data to a server socket created in VB.NET.
' Here is my VB.NET code
Imports System.Net.Sockets
Imports System.Text
Imports System.Net
Public Module MainModule
Private TcpListener As New TcpListener(IPAddress.Parse("10.0.0.100"), 11000)
Dim TcpClient As New TcpClient
Dim NetworkStream As NetworkStream
Public Sub Main()
TcpListener.Start()
While (True)
TcpClient = TcpListener.AcceptTcpClient()
NetworkStream = TcpClient.GetStream()
Dim r_byt(TcpClient.ReceiveBufferSize) As Byte
Dim r_byt_size As Integer = NetworkStream.Read(r_byt, 0, TcpClient.ReceiveBufferSize) - 1
Dim data As String = Encoding.ASCII.GetString(r_byt, 0, r_byt_size)
Console.WriteLine(data)
Dim s_byt() As Byte = Encoding.ASCII.GetBytes("testing")
NetworkStream.Write(s_byt, 0, s_byt.Length)
NetworkStream.Flush()
NetworkStream.Close()
TcpClient.Close()
End While
TcpListener.Stop()
End Sub
End Module
// Here is my Android code
package com.javacodegeeks.android.androidsocketclient;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class Client extends Activity {
private static final String SERVER_IP = "10.0.0.100";
private static final int SERVER_PORT = 11000;
private Socket socket;
private EditText InputText = null;
private Button ButtonSend = null;
private TextView LabelReceived = null;
private Thread thread = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InputText = (EditText)findViewById(R.id.InputText);
ButtonSend = (Button)findViewById(R.id.ButtonSend);
LabelReceived = (TextView)findViewById(R.id.LabelReceived);
thread = new Thread(new ClientThread());
if (thread != null) {
thread.start();
}
ButtonSend.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
try {
if (socket != null) {
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println(InputText.getText().toString());
out.flush();
out.close();
} else {
LabelReceived.setText("socket is null!");
}
} catch (Exception e) {
LabelReceived.setText(e.getMessage());
}
}
});
}
class ClientThread implements Runnable {
public void run() {
try {
InetAddress IAddress = InetAddress.getByName(SERVER_IP);
socket = new Socket(IAddress, SERVER_PORT);
} catch (Exception e) {
socket = null;
}
}
}
}
The two are working, when I press the "send button" it goes to the server, but when I try to do it again nothing is received.
I'm trying to make a client in Android. This clients runs a thread that creates the client socket and launches another thread that is always listening to the socket to receive Strings. Everything is OK when I send a String from the client to a Java server running in a PC, but when I send a String from the server to the Android client the app finishes. Why do I get this error?
Here is the code of the main Activity of the client:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView chatHistorial;
EditText msg;
Socket client;
DataInputStream in;
DataOutputStream out;
Boolean cerrar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread t = new Thread(new Runnable(){
#Override
public void run() {
try{
client = new Socket("192.168.1.33", 4444);
in = new DataInputStream(client.getInputStream());
out = new DataOutputStream(client.getOutputStream());
cerrar = false;
chatHistorial = (TextView) findViewById(R.id.chatHistorial);
msg = (EditText) findViewById(R.id.msg);
ThreadLectura tl = new ThreadLectura(in, cerrar, chatHistorial);
tl.start();
}
catch(Exception e){
// ...
}
}
});
t.start();
findViewById(R.id.enviar).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String cadena = msg.getText().toString();
try {
out.writeUTF(cadena);
} catch (IOException e) {
// ...
}
if(cadena.equals("exit"))
cerrar = true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
class ThreadLectura extends Thread{
DataInputStream in;
String cadena;
TextView chatHistorial;
Boolean cerrar;
public ThreadLectura(DataInputStream in, Boolean cerrar, TextView tv){
this.in = in;
this.cerrar = cerrar;
chatHistorial = tv;
}
#Override
public void run(){
try{
while(!cerrar){
cadena = in.readUTF();
chatHistorial.append("Has recibido: " + cadena);
}
}
catch(IOException ioe){
System.out.println("Error de entrada/salida: "+ioe.getMessage());
}
}
}
It's hard to say without seeing your logcat output, but I'm betting it's because you are attempting to modify the UI from within your background thread. This line within ThreadLectura:
chatHistorial.append("Has recibido: " + cadena);
is probably the issue, as chatHistorial is a TextView. You need to only modify the UI from within the main UI thread.
I need to show toast message when the server is not responding
when I press the login button, some parameters are passed to AgAppMenu screen which use url connection to server and get xml response in AgAppHelperMethods screen. The
probelm is when the server is busy or the network is not avaibale, I can't show toast message on catch block although it shows the log message.
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent ;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class LoginScreen extends Activity implements OnClickListener {
EditText mobile;
EditText pin;
Button btnLogin;
Button btnClear;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.agapplogin);
TextView lblMobileNo = (TextView) findViewById(R.id.lblMobileNo);
lblMobileNo.setTextColor(getResources()
.getColor(R.color.text_color_red));
mobile = (EditText) findViewById(R.id.txtMobileNo);
TextView lblPinNo = (TextView) findViewById(R.id.lblPinNo);
lblPinNo.setTextColor(getResources().getColor(R.color.text_color_red));
pin = (EditText) findViewById(R.id.txtPinNo);
btnLogin = (Button) findViewById(R.id.btnLogin);
btnClear = (Button) findViewById(R.id.btnClear);
btnLogin.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
postLoginData();
}
});
btnClear.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
cleartext();
}
});
/*
*
* btnClear.setOnClickListener(new OnClickListener() { public void
* onClick(View arg0) {
*
* } });
*/
}
public void postLoginData()
{
if (pin.getTextSize() == 0 || mobile.getTextSize() == 0) {
AlertDialog.Builder altDialog = new AlertDialog.Builder(this);
altDialog.setMessage("Please Enter Complete Information!");
} else {
Intent i = new Intent(this.getApplicationContext(), AgAppMenu.class);
Bundle bundle = new Bundle();
bundle.putString("mno", mobile.getText().toString());
bundle.putString("pinno", pin.getText().toString());
i.putExtras(bundle);
startActivity(i);
}
}
#Override
public void onClick(View v) {
}
public void cleartext() {
{
pin.setText("");
mobile.setText("");
}
}
}
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class AgAppMenu extends Activity {
String mno, pinno;
private String[][] xmlRespone;
Button btnMiniStatement;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.agappmenu);
mno = getIntent().getExtras().getString("mno");
pinno = getIntent().getExtras().getString("pinno");
setTitle("Welcome to the Ag App Menu");
AgAppHelperMethods agapp =new AgAppHelperMethods();
// xmlRespone = AgAppHelperMethods.AgAppXMLParser("AG_IT_App/AgMainServlet?messageType=LOG&pin=" + pinno + "&mobile=" + mno + "&source=" + mno + "&channel=INTERNET");
xmlRespone = agapp.AgAppXMLParser("AG_IT_App/AgMainServlet?messageType=LOG&pin=" + pinno + "&mobile=" + mno + "&source=" + mno + "&channel=INTERNET");
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import android.view.View;
import android.view.View.OnKeyListener;
public class AgAppHelperMethods extends Activity {
private static final String LOG_TAG = null;
private static AgAppHelperMethods instance = null;
public static String varMobileNo;
public static String varPinNo;
String[][] xmlRespone = null;
boolean flag = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.agapphelpermethods);
}
protected AgAppHelperMethods() {
}
public static AgAppHelperMethods getInstance() {
if (instance == null) {
instance = new AgAppHelperMethods();
}
return instance;
}
public static String getUrl() {
String url = "https://demo.accessgroup.mobi/";
return url;
}
public String[][] AgAppXMLParser(String parUrl) {
String _node, _element;
String[][] xmlRespone = null;
try {
String url = AgAppHelperMethods.getUrl() + parUrl;
URL finalUrl = new URL(url);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(finalUrl.openStream()));
doc.getDocumentElement().normalize();
NodeList list = doc.getElementsByTagName("*");
_node = new String();
_element = new String();
xmlRespone = new String[list.getLength()][2];
// this "for" loop is used to parse through the
// XML document and extract all elements and their
// value, so they can be displayed on the device
for (int i = 0; i < list.getLength(); i++) {
Node value = list.item(i).getChildNodes().item(0);
_node = list.item(i).getNodeName();
_element = value.getNodeValue();
xmlRespone[i][0] = _node;
xmlRespone[i][1] = _element;
}// end for
throw new ArrayIndexOutOfBoundsException();
}// end try
// will catch any exception thrown by the XML parser
catch (Exception e) {
Toast.makeText(AgAppHelperMethods.this,
"error server not responding " + e.getMessage(),
Toast.LENGTH_SHORT).show();
Log.e(LOG_TAG, "CONNECTION ERROR FUNDAMO SERVER NOT RESPONDING", e);
}
// Log.e(LOG_TAG, "CONNECTION ERROR FUNDAMO SERVER NOT RESPONDING", e);
return xmlRespone;
}
`
AgAppHelperMethods isn't really an Activity. You've derived this class from Activity, but then you've created Singleton management methods (getInstance()) and you are instantiating it yourself. This is bad. Don't do this.
Normally Android controls the instantiation of activities. You don't ever create one yourself (with new).
It looks to me like AgAppHelperMethods just needs to be a regular Java class. It doesn't need to inherit from anything. Remove also the lifecycle methods like onCreate().
Now you will have a problem with the toast, because you need a context for that and AgAppHelperMethods isn't a Context. To solve that you can add Context as a parameter to AgAppXMLParser() like this:
public String[][] AgAppXMLParser(Context context, String parUrl) {
...
// Now you can use "context" to create your toast.
}
When you call AgAppXMLParser() from AgAppMenu just pass "this" as the context parameter.