My project has a light switch which has an IP address and port and accepts strings to control. I am trying to create an application to switch this on and off.
My code works, however after the first click, there is a significant delay between the next click and the switch actually switching.
I have a button for on and off. main.java:
package com.android.lswitch;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class lightswitch extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Handle swon button
Button swon = (Button) findViewById(R.id.swon);
swon.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sw(true);
}
});
// Handle swoff button
Button swoff = (Button) findViewById(R.id.swoff);
swoff.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sw(false);
}
});
}
private void sw(boolean swstate) {
if (swstate == true) {
Thread swonThread = new Thread(new swon());
swonThread.start();
}
if (swstate == false) {
Thread swoffThread = new Thread(new swoff());
swoffThread.start();
}
}
}
and button on java:
package com.android.lswitch;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class swon implements Runnable {
public static final String SERVERIP = "10.0.0.25";
public static final int SERVERPORT = 4000;
public void run(){
try {
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Socket socket = new Socket(serverAddr, SERVERPORT);
String swon = "A55A6B0550000000FFFBDE0030C8";
String but0 = "A55A6B0500000000FFFBDE002066";
PrintWriter out = new PrintWriter( new BufferedWriter
( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(swon);
out.println(but0);
socket.close();
} catch(Exception e) {
}
finally {
}
}
}
button off is virtually the same but with different strings.
I'm new to android coding (and java coding) so can't see where the hold up is. Do I need to flush the strings somewhere? or is there a better way of tackling this project?
Cheers
PrintWriter may be buffered, so you should definitely flush() it before issuing any close() operation on the underlying socket.
It is also preferable to call PrintWriter.close() instead of Socket.close(), e.g., in a finally block, such as:
PrintWriter out = new PrintWriter( new BufferedWriter
( new OutputStreamWriter(socket.getOutputStream())),true);
try {
out.println(swon);
out.println(but0);
out.flush();
} finally {
out.close();
}
Related
So basically I want to create some kind of controller for my pc, where on pc, runs java socket server. The server is working, I have tried it. Also, Port Forwarding in the router is allright. Source code is here :
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static final String ANSI_RESET = "\u001B[0m";
public static final String ANSI_GREEN = "\u001B[32m";
public static final String ANSI_BOLD = "\033[1m";
public static final String ANSI_RED = "\u001B[31m";
public static void main(String[] args) throws IOException {
// Creating server instance
ServerSocket serverSocket = new ServerSocket(2000);
Socket socket = serverSocket.accept();
System.out.println(ANSI_GREEN + "Controller connected" + ANSI_RESET);
// Input Output streams
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
String command = "";
do {
command = dataInputStream.readUTF();
switch (command.trim()){
case "volume up":
Runtime.getRuntime().exec("cmd /c start src\\sk\\dzurik\\main\\volup.bat");
break;
case "volume down":
Runtime.getRuntime().exec("cmd /c start src\\sk\\dzurik\\main\\voldown.bat");
break;
default:
// Unknown command
break;
}
}while (!command.equals("stop"));
socket.close();
System.out.println(ANSI_RED + "Controller disconnected" + ANSI_RESET);
}
}
And it is supposed to interact with the android app, but I got an error and I can't quite figure out why is that so, here is the source code for ActivityMain :
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
private boolean connected;
private DataOutputStream dataOutputStream;
private Socket socket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Pripájanie na server
try {
socket = new Socket("172.0.0.1",2000);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
Toast.makeText(MainActivity.this, "Not Connected!",
Toast.LENGTH_LONG).show();
}
Button VolumeUp = (Button) findViewById(R.id.VolumeUpButton);
VolumeUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
send("volume up");
} catch (IOException e) {
e.printStackTrace();
}
}
});
Button VolumeDown = (Button) findViewById(R.id.VolumeDownButton);
VolumeDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
send("volume down");
} catch (IOException e) {
e.printStackTrace();
}
}
});
Button DisconnectButton = (Button) findViewById(R.id.DisconnectButton);
DisconnectButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
send("stop");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public void send(String command) throws IOException {
if (socket != null){
dataOutputStream.writeUTF(command);
}
else Toast.makeText(MainActivity.this, "Socket is not defined",
Toast.LENGTH_SHORT).show();
}
public void disconnect() throws IOException {
if (socket != null){
socket.close();
}
else Toast.makeText(MainActivity.this, "Socket is not defined",
Toast.LENGTH_SHORT).show();
}
}
So if you could help me with it, I would be thankful, <3
Well the reason for that was silly. When I'm loading data from Stream it says nextLine which means the ending point is \n so I could never get that line because I haven't put it there.
Currently, I have a server(python) and client(android). I am trying to send data from an android to server to another Android using socket. The problem is data looks fine in the server, but garbage value is included when an Android get the Data from server. If I varied the size of string, then it sometimes did not receive the data and after additional sendings, the weird garbage value was received. I think it was some kind of buffer related problem, but I could not figure out the exact problem.
This is output from server : outputFromServer
This is output from android : outputFromAndroid
This is server.py. I am getting data from a client and send it to other clients.
import socket
import time
import select
host = 'myIP' # Symbolic name meaning all available interfaces
port = myPortNumber # Arbitrary non-privileged port
server_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#socket.SOCK_STREAM
server_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#assure reconnect
server_sock.bind((host, port))
server_sock.listen(5)
print(server_sock)
sockets_list = [server_sock]#socket list... multiple clients
clients = {}#socket is the key, user Data will be value
print("Waiting")
def receive_message(client_socket):
try:
data = client_socket.recv(1024)
print("receive Message : " +data.decode('utf-8'))
#return data.decode('utf-8')
return {"data" : data}
except:
return False
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)#read, write ,air on
for notified_socket in read_sockets:
if notified_socket == server_sock: #someone just connected
client_socket, client_address = server_sock.accept()
print(client_socket)
print(client_address)
user = receive_message(client_socket)
if user is False:
print("USER FALSE")
continue
sockets_list.append(client_socket)
clients[client_socket] = user
print("ACCEPTED connection")
else:
message = receive_message(notified_socket)
print("IN ELSE : " + message['data'].decode('utf-8'))
if message is False :
sockets_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
#share this message with everyBody
for client_socket in clients:
print("for loop")
if client_socket != notified_socket:
message_to_send = message['data']
client_socket.send(len(message_to_send).to_bytes(2, byteorder='big'))
client_socket.send(message_to_send)
for notified_socket in exception_sockets:
sockets_list.remove(notified_socket)
del clients[notified_socket]
Here is my Android(java) code for client
package com.example.testing;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ConnectTcp {
private String TAG = "tcp";
private DataOutputStream dos;
private DataInputStream dis;
private Socket socket;
private Thread socketThread;
public ConnectTcp() {
}//connectTcp
void sendMessage(final String message){
socketThread = new Thread() {
public void run(){
try {
if (Thread.interrupted()) { throw new InterruptedException();}
while(!Thread.currentThread().isInterrupted()) {
// ...
try {
socket = new Socket(remoteIP, port);
Log.e(TAG, "success");
}catch (IOException ioe) {
Log.e(TAG,"ERROR");
try {
dos = new DataOutputStream(socket.getOutputStream()); // output
dis = new DataInputStream(socket.getInputStream()); // inpu
dos.writeUTF("CONNECT TO SERVER : "+ message);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
while (true) {
line = (String) dis.readUTF();
Log.w("------서버에서 받아온 값", "" + line);
}
} catch (Exception e) {
}
}
}
} catch (InterruptedException consumed){
/* Allow thread to exit */
}
}//run
};//Thread
socketThread.start();
}
void sendAdditionalMessage(final String data) throws IOException {
Thread sendMessageThread = new Thread() {
#Override
public void run() {
super.run();
try {
dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(data);
} catch (IOException e) {
e.printStackTrace();
}
}
};
sendMessageThread.start();
}
void closeSocket() throws IOException {
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
socketThread.interrupt();
}
}//class
This is MainActivity.java
package com.example.testing;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Handler;
import okhttp3.FormBody;
import okhttp3.RequestBody;
public class MainActivity extends AppCompatActivity {
String getData;
TextView textView;
Button bt_connect;
Button bt_disConnect;
TextView tv_hanium;
int data = 10;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_connect = findViewById(R.id.bt_connect);
bt_disConnect = findViewById(R.id.bt_cancel);
Button bt_goToLogin = findViewById(R.id.bt_goToLogin);
final Button bt_send = findViewById(R.id.bt_send);
final ConnectTcp connectTcp = new ConnectTcp();
bt_connect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
connectTcp.sendMessage("hello world");//connect to server
}
});
bt_disConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
connectTcp.closeSocket();//close socket
} catch (IOException e) {
Log.d("tcp", "fail to close ");
e.printStackTrace();
}
}
});//데이터 전송 중단
bt_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
connectTcp.sendAdditionalMessage("150");// send data
} catch (IOException e) {
e.printStackTrace();
}
}
});
bt_goToLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent goToLogin = new Intent(MainActivity.this, LoginActivity.class);
MainActivity.this.startActivity(goToLogin);
}
});
}
}
The Java DataOutput.writeUTF method sends the length of the string it writes. If you don't want to modify the Java side, you have to modify your receive_message Python function to read the length field. Here's a start:
def receive_message(client_socket):
try:
data = client_socket.recv(2)
# TODO: ensure 2 bytes were returned
expected_length = int.from_bytes(data, byteorder="big")
data = client_socket.recv(expected_length)
if len(data) < expected_length:
# TODO: add a loop to read more data from the socket
pass
# TODO: write your own "modified utf-8" decoder - see
# https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html
print("receive Message : " + data.decode('utf-8'))
Java's DataOutput and DataInput are not really designed for general input/output, and they make integrating with other programming languages difficult as you've discovered. If I were you I would consider migrating to a different protocol, for example one that is based on reading and writing lines of text.
So,It's like the title Say's i have created a Simple android Socket server and Client which Connects over Wifi. Both devices are on the same Wifi Network. The Server Shows the IP Address on which it host the connection....And in the client You have to write the IP Address on which Server is hosted.....
So, My problem is when i am Entering The IP Address in the Client The Server shows "Connected". But when i start to send messages it doesn't send the message to other side neither Server to Client nor Client to server.
//#Server Java File
package inc.teckzy.wif_chat;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.Formatter;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Helper extends AppCompatActivity {
EditText smessage;
TextView chat,display_status;
String str,msg="";
int serverport = 6666;
ServerSocket serverSocket;
Socket client;
Handler handler = new Handler();
WifiManager wmanager;
Boolean Alive;
DataOutputStream out;
DataInputStream in;
Button button_sent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_helper);
wmanager = (WifiManager) getSystemService(WIFI_SERVICE);
#SuppressWarnings("deprecation")
String ip = Formatter.formatIpAddress(wmanager.getConnectionInfo().getIpAddress());
smessage = (EditText) findViewById(R.id.smessage);
chat = (TextView) findViewById(R.id.chat);
display_status = (TextView) findViewById(R.id.display_status);
Thread serverThread = new Thread(new serverThread());
serverThread.start();
Alive = serverThread.isAlive();
display_status.setText("Hosted on: " + ip);
button_sent = (Button) findViewById(R.id.button_sent);
button_sent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Thread sentThread = new Thread(new sentMessage());
sentThread.start();
}
});
}
class sentMessage implements Runnable{
#Override
public void run() {
try{
client = serverSocket.accept();
out = new DataOutputStream(client.getOutputStream());
str = smessage.getText().toString();
msg = msg+"\n Server:" +str;
handler.post(new Runnable()
{
#Override
public void run()
{
chat.setText(msg);
}
});
out.writeBytes(str);
out.flush();
out.close();
client.close();
}catch(IOException e){}
}
}
public class serverThread implements Runnable {
#Override
public void run() {
try {
while (true) {
serverSocket = new ServerSocket(serverport);
client = serverSocket.accept();
handler.post(new Runnable() {
#Override
public void run() {
display_status.setText("Connected");
}
});
/*******************************************
setup i/p streams
******************************************/
in = new DataInputStream(client.getInputStream());
String line = in.readUTF();
while (!line.equals("STOP")) {
msg = msg + "\n Client : " + line;
handler.post(new Runnable() {
#Override
public void run() {
chat.setText(msg);
}
});
}
in.close();
client.close();
}
} catch (Exception e) {
}
}
}
}
//#Client Side Java File
package reciever;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.*;
import java.net.*;
import inc.teckzy.wif_chat.R;
public class ClientSide extends AppCompatActivity {
EditText serverIp,smessage;
TextView chat;
String serverIpAddress = "",msg = "",str;
Handler handler = new Handler();
Button sent,connectPhones;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_side);
chat = (TextView) findViewById(R.id.chat);
serverIp = (EditText) findViewById(R.id.server_ip);
smessage = (EditText) findViewById(R.id.smessage);
sent = (Button) findViewById(R.id.sent_button);
connectPhones = (Button) findViewById(R.id.connect_phones);
//-----------------------Connecting to IP------------------------------//
connectPhones.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals(""))
{
Thread clientThread = new Thread(new
ClientThread());
clientThread.start();
}
}
});
//-------------------------------Initializing sent thread----------------//
sent.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Thread sentThread = new Thread(new sentMessage());
sentThread.start();
}
});
}
class sentMessage implements Runnable
{
#Override
public void run()
{
try
{
InetAddress serverAddr =
InetAddress.getByName(serverIpAddress);
Socket socket = new Socket(serverAddr, 6666); //
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
str = smessage.getText().toString();
str = str + "\n";
msg = msg + "Client : " + str;
handler.post(new Runnable() {
#Override
public void run() {
chat.setText(msg);
}
});
os.writeUTF(str);
os.flush();
os.close();
socket.close();
}
catch(IOException e)
{
}
}
}
public class ClientThread implements Runnable
{
InetAddress serverAddr;
public void run()
{
try
{
while(true)
{
serverAddr = InetAddress.getByName(serverIpAddress);
Socket socket = new Socket(serverAddr, 6666);
/*******************************************
setup i/p streams
******************************************/
DataInputStream in = new
DataInputStream(socket.getInputStream());
String line = in.readUTF();
while (!line.equals("Stop"))
{
msg = msg + "Server : " + line + "\n";
handler.post(new Runnable()
{
#Override
public void run()
{
chat.setText(msg);
}
});
}
in.close();
socket.close();
Thread.sleep(100);
}
}
catch (Exception e)
{}
}
}
}
You are using client = serverSocket.accept(); in server side every time you need to send a message.
And in client side you are trying to create a new Socket connection using new Socket
(serverAddr, 6666); multiple times.
Maintain a single Socket connection and single data input/output stream(do not create multiple instances) and you will be good to go.
See example at:
https://github.com/nabinbhandari/android-socket-messaging
I Solved it Just deleted the "sentMessage" Thread and implemented output stream in "sent.setOnClickListener(new View.OnClickListener()" in both Activity also did some modifications..Here is the working code Activity ...Hope this will help someone
#Server Activity
package inc.teckzy.wifi_chat;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.text.format.Formatter;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Helper extends AppCompatActivity {
EditText smessage;
TextView chat,display_status;
String str,Smsg,Cmsg="";
int serverport = 6666;
ServerSocket serverSocket;
Socket client;
Handler updateConversationHandler =new Handler();
WifiManager wmanager;
DataOutputStream out;
DataInputStream in;
Button button_sent;
StringWriter errors = new StringWriter();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_helper);
wmanager = (WifiManager) getSystemService(WIFI_SERVICE);
#SuppressWarnings("deprecation")
String ip = Formatter.formatIpAddress(wmanager.getConnectionInfo().getIpAddress());
smessage = (EditText) findViewById(R.id.smessage);
chat = (TextView) findViewById(R.id.chat);
display_status = (TextView) findViewById(R.id.display_status);
Thread serverThread = new Thread(new serverThread());
serverThread.start();
display_status.setText("Hosted on: " + ip);
button_sent = (Button) findViewById(R.id.button_sent);
button_sent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
out = new DataOutputStream(client.getOutputStream());
str = smessage.getText().toString();
Smsg = "Server:" + str;
updateConversationHandler.post(new updateUIThread(Smsg));
out.writeUTF(str);
out.flush();
}catch (Exception e) {
e.printStackTrace(new PrintWriter(errors));
updateConversationHandler.post(new updateUIThread(errors.toString()));
}
smessage.getText().clear();
}
});
}
public class serverThread implements Runnable {
#Override
public void run() {
try {
serverSocket = new ServerSocket(serverport);
while (true) {
client = serverSocket.accept();
updateConversationHandler.post(new updateUIThread("Connected"));
/*******************************************
setup i/p streams
******************************************/
in = new DataInputStream(client.getInputStream());
String line = "";
while (!line.equals("STOP")) {
line=in.readUTF();
Cmsg ="Client: "+ line;
updateConversationHandler.post(new updateUIThread(Cmsg));
}
in.close();
client.close();
}
} catch (Exception e) {
e.printStackTrace(new PrintWriter(errors));
updateConversationHandler.post(new updateUIThread(errors.toString()));
}
}
}
class updateUIThread implements Runnable {
private String msg;
updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
chat.setText(chat.getText().toString()+ msg + "\n");
}
}
#Override
protected void onStop() {
super.onStop();
try {
// MAKE SURE YOU CLOSE THE SOCKET UPON EXITING
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And
#Client Activity
package inc.teckzy.wifi_chat.reciever;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.text.format.Formatter;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.Socket;
import inc.teckzy.wifi_chat.R;
public class ClientSide extends AppCompatActivity {
EditText serverIp,smessage;
TextView chat;
String serverIpAddress = "",Smsg,Cmsg = "",str;
Handler updateConversationHandler = new Handler();
Button sent,connectPhones;
Socket socket;
DataInputStream in;
DataOutputStream out;
StringWriter errors = new StringWriter();
WifiManager wmanager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_side);
chat = (TextView) findViewById(R.id.chat);
serverIp = (EditText) findViewById(R.id.server_ip);
wmanager = (WifiManager) getSystemService(WIFI_SERVICE);
smessage = (EditText) findViewById(R.id.smessage);
sent = (Button) findViewById(R.id.sent_button);
connectPhones = (Button) findViewById(R.id.connect_phones);
//-----------------------Connecting to IP------------------------------//
connectPhones.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals(""))
{
Thread clientThread = new Thread(new
ClientThread());
clientThread.start();
}
}
});
//-------------------------------Initializing sent thread----------------//
sent.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
try {
out = new DataOutputStream(socket.getOutputStream());
str = smessage.getText().toString();
Cmsg = "Client: " + str;
updateConversationHandler.post(new updateUIThread(Cmsg));
out.writeUTF(str);
out.flush();
}catch(Exception e){
e.printStackTrace(new PrintWriter(errors));
updateConversationHandler.post(new updateUIThread(errors.toString()));}
smessage.getText().clear();
}
});
}
public class ClientThread implements Runnable
{
InetAddress serverAddr;
public void run()
{
try
{
serverAddr = InetAddress.getByName(serverIpAddress);
socket = new Socket(serverAddr, 6666);
updateConversationHandler.post(new updateUIThread("Connected"));
String ip = socket.getRemoteSocketAddress().toString();
updateConversationHandler.post(new updateUIThread(ip));
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
/*******************************************
setup i/p streams
******************************************/
String line = "";
while (!line.equals("Stop")) {
line=in.readUTF();
Smsg ="Server: " + line + "\n";
updateConversationHandler.post(new updateUIThread(Smsg));
}
out.close();
in.close();
socket.close();
}
catch (IOException e)
{updateConversationHandler.post(new updateUIThread("IO Error"));}
}
}
class updateUIThread implements Runnable {
private String msg;
updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
chat.setText(chat.getText().toString()+ msg + "\n");
}
}
#Override
protected void onStop() {
super.onStop();
try {
// MAKE SURE YOU CLOSE THE SOCKET UPON EXITING
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have an Android app, which should receive and read NMEA-sentences
e.g. $GPGLL,3751.65,S,14507.36,E*77
from a remote TCP-Server using Telnet protocol. I am using the org.apache.commons.net.telnet.TelnetClient library.
What works:
Connecting to Server
Reading some sentences without any error
Problem:
There are more than half of the sentences missing. I guess that it is a timing problem, perhaps this has also to do with the connection which gets restarted in every iteration.
Here is my MainActivity.java:
package com.example.clienttel;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.commons.net.telnet.TelnetClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Go to ClientThread, where NMEA-sentences will be received
int i;
for (i = 0; i < 10000; i++) // 10000 for testing
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
//#Override
public void run() {
TelnetClient telnet = new TelnetClient();
// Variables
String ADDRESS = "194.66.82.11";
int PORT = 51000;
String NMEA = null;
final String TAG = "TestApp";
// Connect To Server
try {
telnet.connect(ADDRESS, PORT);
} catch (IOException e) {
e.printStackTrace();
}
// Process NMEA-sentences
InputStream inStream = telnet.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(inStream));
try {
NMEA = r.readLine();
} catch (IOException e) {
e.printStackTrace();
}
// Ignore "...busy" sentences
if (NMEA != null) {
if(!(NMEA.equals("*** Serial port is busy ***"))) {
Log.i(TAG, NMEA);
}
}
// Disconnect From Server
try {
telnet.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any help would be appreciated!
EDIT:
My code now looks like this:
package com.example.clienttel;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.commons.net.telnet.TelnetClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class MainActivity extends ActionBarActivity {
// Variables
public String ADDRESS = "194.66.82.11";
public int PORT = 50100;
public String NMEA = null;
public final String TAG = "TestApp";
public boolean first = true;
// Handler in mainthread
Handler handler = new Handler() {
public void handleMessage(Message msg) {
String dataString = "";
Bundle bundle = msg.getData();
Log.d("handleMessage", bundle.toString());
if (bundle.containsKey("outgoingString")) {
dataString = bundle.getString("outgoingString");
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ClientThread ct;
ct = new ClientThread();
ct.mhandler=handler;
int i;
for (i = 0; i < 10000; i++) { // 10000 for testing
// Go to ClientThread, where NMEA-sentences will be received
//new Thread(new ClientThread()).start();
ct.start();
}
}
class ClientThread implements Runnable {
public Handler mhandler = null;
#Override
public void run() {
TelnetClient telnet = new TelnetClient();
if (first) {
// Connect To Server in 1st Iteration
try {
telnet.connect(ADDRESS, PORT);
} catch (IOException e) {
e.printStackTrace();
}
first = false;
}
// Process NMEA-sentences
InputStream inStream = telnet.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(inStream));
try {
NMEA = r.readLine();
} catch (IOException e) {
e.printStackTrace();
}
// Handler in ClientThread to send back
Bundle b = new Bundle();
b.putString("outgoingString", NMEA);
Message m = mhandler.obtainMessage();
m.setData(b);
mhandler.sendMessage(m);
}
}
}
but I am not sure about the placement of the handlers
As #EJP said, opening an closing the connection for each line will kill the app...
A better approach is have the thread handle the communication(s) and wait for the next line, passing the data back to the main thread as a bundle message.
There are plenty of examples out there, but essentially you create a handler in your main thread:
Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
String dataString = "";
Bundle bundle = msg.getData();
Log.d("handleMessage", bundle.toString());
if (bundle.containsKey("outgoingString"))
{
dataString = bundle.getString("outgoingString");
}
// you can handle other message types here....
}
and pass it (the handler) to your ClientThread (here, as mhandler) where you can send the messages back:
Bundle b = new Bundle();
b.putString("outgoingString", outgoingText);
Message m = mhandler.obtainMessage();
m.setData(b);
mhandler.sendMessage(m);
Could you help me figure out how to implement Threads to this, so it won't freeze while it waits for the answer from the server?
I've tried for 5 hours or so, i simple can't find a way to use it in a thread, and then return it to set the text with tv.setText();
package zee.rhs.dk;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
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.TextView;
import android.widget.Toast;
public class AndroidClientActivity extends Activity {
private String ip = "90.184.254.246";
private int port = 8081;
private String line;
private TextView tv;
private Button btn;
private Socket socket;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.tv);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(ip, port);
out = new PrintWriter(socket.getOutputStream(), true);
out.println("update");
in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
while ((line = in.readLine()) == null) {
}
tv.setText(line);
} catch (UnknownHostException e) {
Toast.makeText(AndroidClientActivity.this,
"Can't reach ip: " + ip, Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(AndroidClientActivity.this,
"Accept failed at port: " + port, Toast.LENGTH_LONG)
.show();
e.printStackTrace();
} finally {
out.close();
}
}
});
}
}
AsyncTask is what you're looking for. From the help page:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Remember that doInBackground runs in a separate thread, and onPostExecute runs in the UI thread after doInBackground completes.
Put your code, that is responsible for request to server into a separate thread:
Thread thread = new Thread() {
#Override
public void run() {
try {
// put your socket operations here
} catch (InterruptedException e) {
// handle exception if you need
}
}
};
thread.start();