I'm attempting to use my android phone as a keyboard for my PC.
This is done over a local WiFi connection using sockets to create the client/server connection.
I'm using a textwatcher to pick up the change in characters in an editText and then sending those over to the server which then uses a robot class to write that onto the PC. This is all using a Softkeyboard on the android phone.
The issue is that when writing in editText only one character gets sent. and picked up by the server.
e.g. I type on the android phone "a" and the respective keypress will be simulated on the server. If I then type another character it does not read that character but if I delete the "a" and then type another character it will send that character.
Below is the Client side of the code, the Android application.
public class MainActivity extends AppCompatActivity implements View.OnKeyListener {
private final static int portNumber = ****;
private final static String hostName = "192.168.0.8";
private final static String cTest = "Connection Test";
Socket socket = null;
private static String TAG = "test";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread() {
#Override
public void run() {
try {
Log.i(cTest, "attempting to connect");
socket = new Socket(hostName, portNumber);
Log.i(cTest, "Connected");
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getBaseContext(), "Connected Successfully", Toast.LENGTH_SHORT).show();
}
});
EditText editText = (EditText)findViewById(R.id.editText);
editText.addTextChangedListener(editTextWatcher);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(cTest, e.getMessage());
}
}
}.start();
}
private TextWatcher editTextWatcher = new TextWatcher() {
private void sendTextToServer(String send) {
BufferedWriter bw = null;
String textChange = send;
try {
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(textChange);
bw.newLine();
bw.flush();
} catch (IOException e) {
}
}
public void afterTextChanged(Editable s)
{
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
Log.d(TAG, s + " Character Read");
String test = s.toString();
this.sendTextToServer(test);
}
};
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return false;
}
}
The following code is the server side code which is being done in eclipse.
public class ListenServerMain {
private static boolean ifConnected = true;
private final static int portNumber = ****;
public static String readIn;
private static Socket client = null;
private static ServerSocket server = null;
private static BufferedReader in = null;
private static Robot robot = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
robot = new Robot();
server = new ServerSocket(portNumber);
System.out.println("Listening on port :****");
client = server.accept(); //loops until a client server connection is established
System.out.println("Client connected");
//Receive a message from the client
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
while(ifConnected)
{
readIn = in.readLine(); //reads the input received
if(readIn.equalsIgnoreCase("A"))
{
robot.keyPress(KeyEvent.VK_A);
robot.keyRelease(KeyEvent.VK_A);
}
if(readIn.equalsIgnoreCase("B"))
{
robot.keyPress(KeyEvent.VK_B);
robot.keyRelease(KeyEvent.VK_B);
}
if(readIn.equalsIgnoreCase("C"))
{
robot.keyPress(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_C);
}
if(readIn.equalsIgnoreCase("BS"))
{
robot.keyPress(KeyEvent.VK_DELETE);
robot.keyRelease(KeyEvent.VK_DELETE);
}
}
System.out.println("Unable to read user Input"); //if it can't read the input from the Client
System.exit(-1); //system exits
System.out.println("Server Ended");
System.exit(-1);
}
catch (IOException e) {
System.out.println("Can't open the Socket");
System.exit(-1);
}
catch (AWTException e) {
System.out.println("Unable to create Robot");
System.exit(-1);
}
}
}
Is there any way in which I can successfully read and send each character entered in the editText field?
If any further clarification about this is necessary let me know.
Thanks
Related
I'm trying to write a simple client/server program, where the client is an android app and the server is a Raspberry Pi 4. All I want to do is allow the client to type a message and have the Raspberry Pi display the message on the terminal. However, my app keeps throwing an exception at the out.writeObject(message_text) line in the sendMessage() method.
public class MainActivity extends AppCompatActivity {
private EditText message;
private Button send;
private ObjectOutputStream out;
private Socket socket;
private String raspi_ip = "enter ip here";
private int raspi_portnum = 12345;
Client client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
message = findViewById(R.id.message_text);
send = findViewById(R.id.send_button);
try{
client = new Client(raspi_ip,raspi_portnum);
client.start();
} catch (Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Error! ").setMessage("Couldn't connect to server.").setNeutralButton("OK", null).create().show();
}
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
client.sendMessage();
}
});
}
private void closeConnection(){
try{
out.close();
socket.close();
} catch (Exception e){
e.printStackTrace();
}
}
#Override
protected void onStop(){
super.onStop();
closeConnection();
}
private class Client extends Thread {
private String ip_address;
private int port_number;
public Client(String ipaddress,int portnum){
this.ip_address = ipaddress;
this.port_number = portnum;
}
#Override
public void run() {
super.run();
connectToServer(ip_address,port_number);
}
public void connectToServer(String ipaddress, int portnum){
try{
socket = new Socket(InetAddress.getByName(ipaddress),portnum);
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
}catch (Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Error! ").setMessage("Couldn't connect to server.").setNeutralButton("OK", null).create().show();
}
}
public void sendMessage(){
String message_text = message.getText().toString();
try{
out.writeObject(message_text);
out.flush();
} catch (Exception e) {
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Error! ").setMessage("IO Exception.").setNeutralButton("OK", null).create().show();
}
}
}
}
Here is the server side java program:
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class RaspPiServer {
private ServerSocket server;
public RaspPiServer(){
}
public static void main(String[] args){
RaspPiServer server = new RaspPiServer();
server.runServer();
}
public void runServer(){
try{
server = new ServerSocket(12345,100);
while (true){
new Controller(server.accept()).start();
}
} catch(Exception e){
e.printStackTrace();
}
}
private class Controller extends Thread {
private Socket socket;
private ObjectInputStream input;
private String in;
public Controller(Socket socket){
this.socket = socket;
System.out.println("New client at " + socket.getRemoteSocketAddress());
}
#Override
public void run(){
try{
input = new ObjectInputStream(socket.getInputStream());
while (!(in = (String)input.readObject()).equals("close")){
System.out.println(in);
}
} catch(Exception e){
e.printStackTrace();
} finally {
closeConnection();
System.out.println("Connection with client # " + socket.getRemoteSocketAddress() + " closed");
}
}
private void closeConnection() {
try {
input.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Is there an easy fix here, or am I missing something bigger?
I'm trying to send commands from my phone to my computer using Sockets.
I've tryed the answers here:
Android and PC Socket connection
But after some digging i found out that you need to use a Async task so i tryed this:
Using AsyncTask for android network connection
But for some reason my socket times out. Is there a way to find out why? because from the error i can't tell:
The error from Logcat:
And this is the client code:
public class MainActivity extends AppCompatActivity {
private Socket client;
private PrintWriter printwriter;
private EditText textField;
private Button button;
private String message;
private static final int SERVERPORT = ####;
private static final String SERVER_IP = "########";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textField = (EditText) findViewById(R.id.editText1); // reference to the text field
button = (Button) findViewById(R.id.button1); // reference to the send button
}
public void onClick(View view) {
message = textField.getText().toString();
textField.setText(""); // Reset the text field to blank
new AsyncAction().execute();
}
private class AsyncAction extends AsyncTask<String, Void, String> {
protected String doInBackground(String... args) {
try {
System.out.println("background running");
System.out.println(message);
client = new Socket(SERVER_IP, SERVERPORT); // connect to server
System.out.println(client.isConnected());
System.out.println("test");
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(message); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); // closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
I wrote a Server for this in Java and tested it in the emulator.
I had two things to do :
The server IP is "10.0.2.2" if you are using an Android Emulator. LocalHost is de Emulator Virtual Machine.
Your application needs Permission Internet in manifest
Here is the server Code
/**
*
* #author Jean-Pierre
*/
public class SocketServer {
private static final int portnumber = 4444;
public static void main(String[] args) {
SocketServer socketServer = new SocketServer();
socketServer.run();
}
/**
* Reads a String from the client
* Converts it to Uppercase
* and sends it Back.
*/
private void run() {
try {
ServerSocket serverSocket = new ServerSocket(portnumber);
Socket clientSocket = serverSocket.accept();
System.out.println("connected with :" + clientSocket.getInetAddress());
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
InputStreamReader is =
new InputStreamReader(clientSocket.getInputStream());
BufferedReader in =
new BufferedReader(is);
while (true) {
String line = in.readLine();
if (line != null) {
System.out.println("recieved:" + line);
out.println(line.toUpperCase());
}
}
} catch (IOException ex) {
Logger.getLogger(SocketServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Hi every one i am developing a chat application in android for that i have developed a sever in java to route messages. The system works in such a way that after connecting to server the clients send its id to server. Now the problem i am having is that some times the server receives the id from client and most of the time the server don't receive the id. Please help me i have no idea why is it behaving like this
the code for server
System.out.println("server starting at port: "+ portnumber);
serverSocket = new ServerSocket(portnumber);
while(true){
System.out.println("waiting for client# "+ clientno);
//connecting to client's call
Socket socket = serverSocket.accept();
System.out.println("Client# "+ clientno +" connected!!!");
//recieving clients name
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int idOfClient = br.read();
System.out.println("" + idOfClient);
}
and the code for client
public class MainActivity extends Activity {
private static final String TAG = "ChatActivity";
private static final String hostname="192.168.0.100";
private static final int portnumber=60123;
private ChatArrayAdapter chatArrayAdapter;
private ListView listView;
private EditText chatText;
private Button buttonSend;
private boolean side = false;
private BufferedWriter bw;
private BufferedReader br;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonSend = (Button) findViewById(R.id.send);
listView = (ListView) findViewById(R.id.msgview);
chatArrayAdapter = new ChatArrayAdapter(getApplicationContext(), R.layout.right);
listView.setAdapter(chatArrayAdapter);
chatText = (EditText) findViewById(R.id.msg);
chatText.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
try {
return sendChatMessage();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
});
Thread thread=new Thread(){
public void run() {
try {
chatArrayAdapter.add(new ChatMessage(!side, "Connecting to server"));
final Socket socket = new Socket(hostname, portnumber);
chatArrayAdapter.add(new ChatMessage(!side, "Connected to server"));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(2);
bw.newLine();
bw.flush();
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true) {
//if (br.ready()) {
//chatText.setText(br.readLine());
chatArrayAdapter.add(new ChatMessage(!side, br.readLine()));
//}
}
} catch (Exception e) {
}
}
};
thread.start();
buttonSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
try{
sendChatMessage();
}
catch(Exception e){
}
}
});
listView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
listView.setAdapter(chatArrayAdapter);
//to scroll the list view to bottom on data change
chatArrayAdapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
listView.setSelection(chatArrayAdapter.getCount() - 1);
}
});
}
private boolean sendChatMessage() throws IOException {
String msg=chatText.getText().toString();
try {
bw.write(msg);
bw.newLine();
bw.flush();
chatArrayAdapter.add(new ChatMessage(side, msg));
}
catch(Exception e){
chatArrayAdapter.add(new ChatMessage(side,"Message not sent"));
}
chatText.setText("");
return true;
}
}
Try closing the bufferedReader after the print like this
int idOfClient=br.read();
System.out.println(""+idOfClient);
br.close();
I have made an application that opens up a socket via a thread and updates based on what is typed. Here is the code:
Server.java:
public class Server {
public static void main(String[] args) throws IOException {
int portNumber = 2392;
boolean listening = true;
System.out.println("Server: Running...");
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
System.out.println("Server: Connected to Client!");
while (listening) {
new ServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection( '" + e.getMessage() + "' );");
} finally {
System.out.println("Server: Disconnecting...");
}
}
}
Server Thread.java:
public class ServerThread extends Thread {
private Socket socket = null;
Scanner reader = new Scanner(System.in);
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
public void run() {
System.out.println("Ruasd");
try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String outputLine = "";
while (!outputLine.equals("Disconnect")) {
outputLine = reader.nextLine();
out.println(outputLine);
}
socket.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client.java:
public class MainActivity extends Activity {
private Socket socket;
private TextView status;
private BufferedReader in;
private Handler mHandler;
private static final int SERVERPORT = 2392;
private static final String SERVER_IP = "...ip#...";
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_vitals);
status = (TextView) findViewById(R.id.text_status);
new Thread(new CommunicationThread()).start();
}
#Override
protected void onStop() {
super.onStop();
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class CommunicationThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
final String fromServer = in.readLine();
System.out.println("Server: " + fromServer);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
status.setText(fromServer);
}
});
if (fromServer.equals("Disconnect."))
break;
}
} catch (IOException e) {
e.printStackTrace();
}
It works perfectly the first time and outputs to the status TextView correctly. However, when I restart the application, it outputs every other word. For instance, If I type "Hey" "Hi "You" "How", I will see "Hi" and "How" in the TextView the second time I start the application.
What's really odd to me is that when I do System.out.println("Server: " + fromServer) it is outputting all values. Any suggestions are greatly appreciated.
Ok I think I found the problem (got it working for me, that is). In your CommunicationThread, you didn't have a while loop. Also, you need to iterate the server's input until it is null. See below:
class CommunicationThread implements Runnable {
#Override
public void run() {
try {
// keep the connection alive.
while (true) {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String fromServer;
// get server messages until there are none
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
status.setText(fromServer);
}
});
if (fromServer.equals("Disconnect."))
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Please get back to me on how it works out :)
i got a little problem with my little application by using java Sockets.
if i start my Sockert-Server on pc and i'm connected withmy phone via wifi in the same network by using the (intern) network IP i can send some stuff to my server.
But if i try to send a message via the mobile internet connection,it doesn´t work..there is also no error or something else :/
Here is my android class:
public class Sockets extends Activity {
EditText textOut;
EditText ipAddress;
TextView textIn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket);
textOut = (EditText)findViewById(R.id.textout);
Button buttonSend = (Button)findViewById(R.id.send);
ipAddress = (EditText)findViewById(R.id.ipAddress);
buttonSend.setOnClickListener(buttonSendOnClickListener);
}
Button.OnClickListener buttonSendOnClickListener
= new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
new DatagrammClient(ipAddress.getText().toString(),textOut.getText().toString()).execute("");
textOut.setText("");
}};
private static class DatagrammClient extends android.os.AsyncTask<String, Void, String> {
final static String LOGIN = "LOGIN";
final static String LOGOUT = "LOGOUT";
static int port = 1234;
static int length = 1024; // Länge eines Pakets
static DatagramSocket socket = null;
static InetAddress ia = null;
static DatagramPacket packet;
String hostname = "";
String msg ="";
public DatagrammClient(String hostname,String msg) {
this.hostname = hostname;
this.msg = msg;
}
/**
* Send the login package and open socket
*
* #param servername
* #throws IOException,UnknownHostEception
*/
private static void connectToServer(String servername) throws IOException,UnknownHostException{
packet = null;
byte[] ba = LOGIN.getBytes();
try {
socket = new DatagramSocket();
ia = InetAddress.getByName(servername);
packet = new DatagramPacket(ba, ba.length, ia, port);
Log.d("servername",servername);
Log.d("Internetaddress",ia.toString());
Log.d("SOCKET",socket.toString());
// sende Anmeldung
socket.send(packet);
} catch (SocketException se) {
Log.d("SocketException",se.toString());
}
catch (UnknownHostException he) {
Log.d("UnknownHost: ",he.toString());
}
catch (IOException e) {
Log.d("IOException: ",e.toString());
}
}
public static void sendMessage(String message, String hostname) throws UnknownHostException, IOException{
//if (socket == null){
DatagrammClient.connectToServer(hostname);
//}
DatagrammClient.sendMessageToServer(message);
DatagrammClient.readMessageFromServer();
//Close connection -> Send logout Package?
}
private static void readMessageFromServer(){
// Lesen der empfangenen Pakete erfolgt in eigenem Thread
LeseThread lt = new LeseThread( socket );
}
private static void sendMessageToServer(String message){
byte[] ba = null;
try {
if (!message.equals(LOGOUT)) {
// message = br.readLine();
ba = message.getBytes();
packet.setData(ba, 0, ba.length);
socket.send(packet);
Log.d("Message:",packet.toString());
} else {
ba = LOGOUT.getBytes();
packet.setData(ba, 0, ba.length);
socket.send(packet);
// Exit the system -> do we need to close the socket clientside?
//socket.close();
System.exit(0);
}
} catch (IOException e) {
System.err.println("Ausnahmefehler: " + e);
Log.d("IOEXCEPTION_MESSAGE_TO_SERVER:",e.toString());
}
}
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
try {
DatagrammClient.sendMessage(msg, hostname);
}
catch(Exception e){
Log.d("Error: ",e.toString());
}
return null;
}
}
}
The permission to use the INTERNET is set in the Manifest..