Send and receive text data in background thread - android

I'm new in developing for Android. My app is client whith outside TCP server. I need to send text data from EditText to server in background thread with Socket. Answer from server i need to add to TextView. I see many examples, but don't see example which i could understand. So i need simple example specially for me, as that possible. Sorry for my English.
AsyncTask only for one-time using. I need only Thread. As i understand i need: Thread(Runnable), Handler, Message, Looper.. But i don't understand how use all this classes for me.
ublic class ServerWork extends Thread{
public static final Character PREFIX = ###;
public static final Character SUFFIX = ###;
public static final int SERVERPORT = ###;
public static final String SERVER_IP = ###;
private Socket socket;
String response;
String inputStr;
public ServerWork(String inputStr){
this.inputStr = inputStr;
}
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
String str = PREFIX + inputStr + SUFFIX;
PrintWriter printOut = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
BufferedReader inputBuffer = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
printOut.println(str);
printOut.flush();
char buf[] = new char[ 1000 ];
int count = inputBuffer.read( buf );
response = new String( buf, 0, count );
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

Communicate with an AsyncTask in Android?

I'm running a socket client in my AsyncTask. I need to find a way to call send externally. Ex: socketClient.send(msg); SocketClient is defined in a service. Send will be called when the UI sends a broadcast and the service receives it. So far all my attempts have caused the app to crash.
Here is my code:
public class SocketClient extends AsyncTask<Void, Void, Void> {
private String ip;
private int port;
private Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private boolean connected;
String devID;
public SocketClient(String ip, int port, String devID){
this.ip = ip;
this.port = port;
this.devID = devID;
connected = true;
}
#Override
protected Void doInBackground(Void... arg0){
try{
socket = new Socket(ip, port);
} catch(Exception ex){
socket = null;
}
try{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
send(new SocketMessage("ident", "sdas", "", ""));
while(connected) {
SocketMessage msg = new SocketMessage(in.readLine());
handle(msg);
}
//clean up
out.println(new SocketMessage("quit", "","", ""));
out.flush();
} catch(Exception ex){
ex.printStackTrace();
}
finally{
try{
connected = false;
out.close();
in.close();
socket.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
return null;
}
public void handle(SocketMessage msg){
}
public synchronized void send(SocketMessage msg){
out.println(msg.getJSON());
out.flush();
}
}
The AsyncTask is not designed for long running processes. In that case you are better of using a Thread. See the developer guide for Connecting Techniques.
Try an event bus like Otto from Square or Event Bus from Green Robot. IPC is difficult in Android and these libraries abstract it to make it less painful to work with.

Android 6.0 cant create socket

I cant create a simple TCP connection to my server.
I created a AsyncTask to send messages, but it didn't work.
I added INTERNET and ACCESS_NETWORK_STATE to the permissions.
I don't know what else to try.
public class ServerCommunicator extends AsyncTask<String,Void,Void>{
public static String SERVER_IP = "192.168.2.148";
public static int SERVER_PORT = 1337;
public static String SERVER_PW = "adsfadsf";
public Context context;
#Override
protected Void doInBackground(String... params) {
//Create Command
CommandFactory cmdFactory = new CommandFactory();
Command cmd = cmdFactory.createCommand();
System.out.println("Cmd created..");
//-----
try {
System.out.println(SERVER_IP);
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
System.out.println("Created serverAddr "+ SERVER_IP);
Socket socket = new Socket(serverAddr,SERVER_PORT);
System.out.println("Socket created..");
//sends the message to the server
PrintWriter mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
String msg2Send = Crypter.Encrypt(cmd.toString(), SERVER_PW);
sendMsgAsByteArr(socket, msg2Send);
Command recCmd = cmdFactory.extractCommandFromStr(receiveMsg(socket));
socket.close();
Toast.makeText(context, recCmd.id, Toast.LENGTH_LONG).show();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static void sendMsgAsByteArr(Socket socket, String msg) {
try {
socket.getOutputStream().write(msg.getBytes());
System.out.println("sent cmd..");
} catch (IOException e) {
e.printStackTrace();
}
}
private static String receiveMsg(Socket socket) {
String msg = "";
int c;
ArrayList<Byte> incoming = new ArrayList<Byte>();
try {
while((c = socket.getInputStream().read())!=-1) {
incoming.add((byte)c);
}
byte[] allBytes = new byte[incoming.size()];
for(int i = 0; i < incoming.size(); i++) {
allBytes[i] = incoming.get(i);
}
msg = new String(allBytes);
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
}
My program runs till Socket socket = new Socket(serverAddr, SERVER_PORT); then it stops. It doesn't show any stack trace or errors.
Any ideas?
I debugged your code, and while there were multiple issues, none were related to Android 6.
I created a simplified version of your code and got it working.
One issue is that your context reference was null, so I set it in the constructor.
Another issue is that you were trying to show a Toast on a background thread, which won't work.
Another issue was your send and receive methods, they didn't work for me.
Here's the simplified code that I got working with a TCP/IP server, tested on both Android 4.4.4 and Android 6.
You can take this and expand on it as needed:
public class ServerCommunicator extends AsyncTask<String,Void,String> {
public static String SERVER_IP = "11.222.33.444";
public static int SERVER_PORT = 1234;
public Context context;
public ServerCommunicator(Context c) {
this.context = c;
}
#Override
protected String doInBackground(String... params) {
try {
System.out.println(SERVER_IP);
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
System.out.println("Created serverAddr "+ SERVER_IP);
Socket socket = new Socket(serverAddr,SERVER_PORT);
System.out.println("Socket created..");
//sends the message to the server
PrintWriter mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
String msg2Send = "{\"HelloWorld\", \"1234\"}";
mBufferOut.println(msg2Send);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String result = in.readLine();
System.out.println("result: " + result);
socket.close();
return result;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
}

How to put a timer to a TCP socket?

I need your help. I want to do this: I have a socket TCP and a Timer task in my IntentService. This is my code:
protected void onHandleIntent(Intent intent)
{
String add = intent.getStringExtra("address");
Log.d("add",add);
int porta = Integer.parseInt(intent.getStringExtra("port"));
InetAddress serverAddr = null;
try
{
serverAddr = InetAddress.getByName(add);
socket = new Socket(serverAddr, porta);
socketHandler.setSocket(socket);
final PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
out.print("go");
out.flush();
final byte[] bytes = new byte[1000];
int counter;
String reader;
final InputStream data = socket.getInputStream();
int numRead = 0;
if ((numRead = data.read(bytes)) >= 0)
{
reader=new String(bytes, 0, numRead);
}
if (reader.equals("Let's go"))
{
//socket connected
}
pingTimer = new Timer();
pingTimer.scheduleAtFixedRate(new TimerTask() {
String reader; int r;
public void run()
{
out.write("ping");
out.flush();
if(out.checkError())
{
onDestroy();
}
}
}, 0, 20000);
InputStream readeIn = socket.getInputStream();
char [] buffer = new char[1024];
BufferedReader in = new BufferedReader(new InputStreamReader(readeIn));
while((counter = in.read(buffer)) != -1)
{
//read here
}
catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
onDestroy();
}
}
public void onDestroy()
{
//destroy socket
}
and it works well. Now I want to do this: I want to put a timer to the socket. So, the socket is up for 3 minutes; if it receives something, re-put 3 minutes to listen, but if in these 3 minutes socket doesn't receive anything, I want to close the socket. How can I do it?
Thanks for your answers.
You need to call Socket.setSoTimeout() with an argument of 3*60*1000 which corresponds to three minutes (times 60 to give seconds, times 1000 to give milliseconds), and handle the resulting SocketTimeoutException accordingly.

tcp socket problem on android

I need to use the tcp socket connection to get the data from a bluebox, if I input a comment, such as "getcolor", the bluebox will send me the information like"red, blue".
In this case the bluebox as a server and I do not need to program on it, but I have problem to show the information on the EditText.
public class sender {
public static void main(String[] args)throws IOException{
Socket socket = new Socket("192.168.1.176",14111);
OutputStream out = socket.getOutputStream();
BufferedReader msg = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter ou = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)),true);
String buffer = new String("");
String ms = "";
while(true)
{
while(in.ready())
buffer+= in.readLine()+ "\n";
String[] line = buffer.split("\n");
while(msg.ready())
ms = msg.readLine();
if(ms.equals("exit"))
{
break;
}
if(!ms.equals(""))
{
ou.println(ms);
ou.flush();
ms = "";
}
if(!buffer.equals(""))
{
System.out.print(buffer);
buffer = "";
}
}
in.close();
out.close();
socket.close();
}
}
this java code works, but it fails in the android code below:
public class BlueBoxApp extends Activity {
/** Called when the activity is first created. */
Context appInstance = this;
private EditText info;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
info = (EditText)findViewById(R.id.EditText01);
try{
InetAddress serverAddr = InetAddress.getByName("192.168.1.176");//TCP服务器IP地址
Log.d("TCP", "server,receiving...");
Socket socket = new Socket(serverAddr,14111);
try {
OutputStream out = socket.getOutputStream();
BufferedReader msg = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter ou = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)),true);
String buffer = new String("");
String ms = "getsensorno";
Log.d("TCP", "sending:'"+ms+"'");
while(true)
{
while(in.ready())
buffer+= in.readLine()+ "\n";
while(msg.ready())
ms = msg.readLine();
if(ms.equals("exit"))
{
break;
}
if(!ms.equals(""))
{
ou.println(ms);
ou.flush();
ms = "";
}
if(!buffer.equals(""))
{
info.setText(buffer);
buffer = "";
}
}
} catch (Exception e) {
Log.e("TCP", "error",e);
}finally{
socket.close();
}
}catch(Exception e){
Log.e("TCP", "error",e);
}
}
}
what is the problem and how to set a thread for it? Thanks!
The problem, as you indicated, is that you are doing the networking part on the main thread.
Setting a new thread is easy, consider using AsyncTask. Please read the documentation (which is very good) before jumping to implement it, it will make it much easier IMHO.
Also, make sure you have internet permission in your AndroidManifest.xml

Android TCP Client in phone has problems in communicating with external server

I have a TCP Client in Android (Java program in Eclipse). The server was another Java app running in Eclipse. Everything works fine in this situation.
When I tried to receive message from my colleague's app (developed in Rhapsody and I think C++), I receive the message only after his app is closed and not while his app is running and sending messages. Do you have any idea why this happens?
Thank you for the time and effort on this.
Cheers,
Madhu
The java server is like this:
public class TCPSendServer implements Runnable{
public static final String SERVERIP = "192.168.178.24";
public static final int SERVERPORT = 1200;
//static Category cat = Category.getInstance(TCPSendServer.class.getName());
//cat.debug("Start of main()");
public void run() {
try {
System.out.println("S: Connecting...");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
String msg = "<MSG><N>shiftDirection</N><V>1</V></MSG>";
String msg1 = "<MSG><N>vehicleSpeed</N><V>120</V></MSG>";
String msg2 = "SD<!N><V>0<!V><!MSG>";
//while (true) {
Socket client = serverSocket.accept();
try {
System.out.println("S: Sending: '" + msg + "'");
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(client.getOutputStream())),true);
Thread.sleep (5000);
out.println(msg);
Thread.sleep (5000);
//out.println(msg2);
Thread.sleep (5000);
out.println(msg1);
//out.flush();
System.out.println("S: Sent.");
System.out.println("S: Done.");
} catch(Exception e) {
System.out.println("S: Error");
e.printStackTrace();
} //finally {
// client.close();
//}
//}
} catch (Exception e) {
System.out.println("S: First try error");
e.printStackTrace();
}
}
public static void main (String a[]) {
Thread desktopServerThread = new Thread(new TCPSendServer());
desktopServerThread.start();
}
}
The Android client code:
Main activity:
public class TCPListen extends Activity implements TCPListener {
private TextView mTitle;
public String data[] = new String[2];
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
// Set up the window layout
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.main);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
// Set up the custom title
mTitle = (TextView) findViewById(R.id.title_left_text);
mTitle.setText(R.string.app_name);
mTitle = (TextView) findViewById(R.id.title_right_text);
//TcpServiceHandler handler=new TcpServiceHandler(this);
//handler.execute("192.168.178.24");
TcpServiceHandler handler = new TcpServiceHandler(this,this);
Thread th = new Thread(handler);
th.start();
}
public String[] callCompleted(String source){
Log.d("TCP", "Std parser " + source);
mTitle.setText(source);
//String data[] = new String[2];
//if (source.matches("<MSG><N>.*</N><V>.*</V></MSG>")) {
Document doc = null;
try{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = (Document) db.parse(new ByteArrayInputStream(source.getBytes()));
NodeList n = doc.getElementsByTagName("N");
Node nd = n.item(0);
String msgName = nd.getFirstChild().getNodeValue();
NodeList n1 = doc.getElementsByTagName("V");
Node nd1 = n1.item(0);
String tmpVal = nd1.getFirstChild().getNodeValue();
data[0] = msgName;
data[1] = tmpVal;
Log.d("TCP", "Inside Std parser " + data[0] + " " + data[1]);
//actionOnData(data[0], data[1]);
}
catch(Exception e){
e.printStackTrace();
}
Log.d("TCP", "Just outside Std parser " + data[0] + " " + data[1]);
return data;
//} else Log.d("TCP", "Message in wrong format " + source);
//mTitle.setText("Message in wrong format " + source);
//return data;
}
Interface:
public interface TCPListener {
public String[] callCompleted(String msg);
}
TCPServiceHandler:
public class TcpServiceHandler implements Runnable {
TCPListener _listener;
private Activity _act;
public TcpServiceHandler(TCPListener listener, Activity act){
_listener = listener;
_act = act;
}
public synchronized void run() {
// TODO Auto-generated method stub
//if(socket==null){
try {
InetAddress serverAddr = InetAddress.getByName("192.168.178.25");
Socket socket = new Socket(serverAddr, 1200);
//
while(true){
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final String str = in.readLine();
this._act.runOnUiThread(new Runnable(){
public void run() {
_listener.callCompleted(str);
}
});
}
catch(Exception e){
e.printStackTrace();
}
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is problem with the SERVERIP here. Are you running your app from an emulator in your local machine? Your emulator is not part of your LAN. Emulator runs behind a virtual router/firewall service that isolates it from your development machine's network interfaces and settings and from the internet.
So you need to use network redirections or port forwarding to achieve communication with the server which is on a separate machine.
If you are running the app on a device then you can make that device as part of your network and then it should work.
There has been a solution, at least for the time being. I use readLine() to read contents of sockets and this expects \n or \r or similar characters until it returns the contents. This was not the issue for me when both server and client were in Java. But when the client had to receive messages from a different app, I faced this problem. It was overcome by just adding \n to the end of message sent by the other app.

Categories

Resources