I'd like write an app to transfer data between 2 android devices on the same wifi network, like as there is a share folder.
How can i do this?
Thanks
EDIT (My solution):
My Server wait for request
private boolean startServer() {
try {
server = new ServerSocket(port);
} catch (IOException ex) {
ex.printStackTrace();
return false;
}
return true;
}
public void runServer() {
while (this.go) {
try {
Log.d("BurgerClub", "Server in attesa di richieste");
Socket s1 = server.accept();
OutputStream s1out = s1.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s1out));
BufferedReader br = new BufferedReader(new FileReader(this.path));
String counter = br.readLine();
counter = counter != null ? counter : "000";
br.close();
bw.write(counter);
bw.close();
s1.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
My Client (Runnable object)
public void run() {
try {
this.openConnection();
// Se il socket รจ connesso
if( !this.s1.isClosed() ) {
InputStream is = this.s1.getInputStream();
BufferedReader dis = new BufferedReader(new InputStreamReader(is));
line = dis.readLine();
if( !this.previousCounter.equals(line.trim()) ) {
((BurgerClub_MonitorActivity) counterContext).runOnUiThread(new Runnable() {
#Override
public void run() {
TextView edit = (TextView)(((BurgerClub_MonitorActivity) counterContext).findViewById(R.id.textActionCounter));
edit.setText(line);
}
});
this.previousCounter = line.trim();
}
dis.close();
}
} catch (ConnectException connExc) {
connExc.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Throwable ex) {
ex.printStackTrace();
}
One device needs to serve as a server and the other one will be the client.
The basic flow needs to be something of this sort:
Server device opens a socket and listens on it.
Server device broadcasts the local IP and port it's listening on.
Client device receives broadcast and initiates a connection.
Perform data transfer.
Read about NFC (Near field communication)
http://developer.android.com/guide/topics/connectivity/nfc/index.html
Related
I'm new to Android, somewhat new to socket programming. I have two devices, running Android 5.1, connected with WiFi direct (not sure if that's relevant). I have a service where the server listens for a request on a socket, then returns a reply back to the client.
Likewise the client code sends a request and listens for the reply from the server. The server is sending the response, but the client never gets the message and the socket times out.
Server test code:
while (true) {
try {
Log.i(TAG, "test waiting for a request");
mServer = new ServerSocket(PORT);
Socket socket = mServer.accept(); //Block to receive message //
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.i(TAG, "Message received! " + in.readLine());
String msg = "This is my reply.";
OutputStream outputStream = socket.getOutputStream();
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
out.println(msg);
out.flush();
out.close();
} catch (SocketException e) {
Log.e(TAG, "Socket Accept Interrupted", e);
} catch (IOException e) {
Log.e(TAG, "Socket Failure", e);
} finally {
if (mServer != null && mServer.isBound()) {
try {
mServer.close();
} catch (IOException ioException) {
Log.e(TAG, "Failed to close socket trying to recover from SocketException", ioException);
}
}
}
}
Client test code:
Socket socket = null;
SocketAddress addr = new InetSocketAddress(host, PORT);
int socketTOms = 5000;
try {
socket = new Socket(host, PORT);
socket.setKeepAlive(false);
String syncReq = "Request to server.";
//Send Request//
OutputStream outputStream = socket.getOutputStream();
outputStream.write(syncReq.getBytes());
socket.setSoTimeout(socketTOms);
//Rcv reply//
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.i(TAG, "Message received! " + in.readLine());
} catch (SocketTimeoutException e) {
Log.e(TAG, "Timeout while reading from socket: timeout=" + socketTOms);
} catch (Exception e) {
Log.e(TAG, "Exception", e);
} finally {
if (socket != null && socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Exception while closing socket", e);
}
}
}
I'm running the server and client on two different devices through Android Studio and can see in the logs that the server receives the request and sends the reply, but the client always throws SocketTimeoutException. I saw else where that socket.setKeepAlive(false) would fix the problem, but it doesn't seem to have any effect.
Seems simple enough, but I can't see what I'm missing here.
May be try this line of code before infinite loop mServer = new ServerSocket(PORT);
Did you try to create thread in sever side app. This makes the process to run in parallel so that while server is waiting for request the application does not gets hang. First of all try this code for localhost . To find Inetaddress just use InetAddress.getLocalHost(). Then run this. For communication with different devices there is service provided that is called (NSD) (Network Service Discovary).
But if you want to run this way I have written a code for you.
Server side code
TextView textView;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=(TextView)findViewById(R.id.textView);
button=(Button)findViewById(R.id.button);
button.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
connect();
}
}
);
}
public void connect()
{
MyServer myServer= new MyServer();
myServer.setEventListener(this);
myServer.startListening();
}
#Override
public void Display(String message) {
textView.setText("Client - "+ message);
}
}
Client side code
TextView textView;
Button button;
Thread mThread;
Socket clientSocket;
Button sendBtn;
public String userText1;
ObjectOutputStream output;
EditText editText;
Object userText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=(TextView)findViewById(R.id.textView);
button=(Button)findViewById(R.id.button);
sendBtn=(Button)findViewById(R.id.sendBtn);
editText=(EditText)findViewById(R.id.editText);
sendBtn.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
userText=editText.getText().toString();
start();
}
}
);
public void start()
{
mThread= new Thread(new Runnable() {
#Override
public void run() {
try {
clientSocket = new Socket("127.0.0.1", 2001);
Log.v("binaya", "client socket created");
output = new ObjectOutputStream(clientSocket.getOutputStream());
output.writeObject(userText);
Message serverObj = Message.obtain();
ObjectInputStream input = new ObjectInputStream(clientSocket.getInputStream());
String strMsg = input.readObject().toString();
serverObj.obj = strMsg;
mHandler.sendMessage(serverObj);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
mThread.start();
}
Handler mHandler= new Handler()
{
#Override
public void handleMessage(Message msg) {
msgDisplay(msg.obj.toString());
}
};
private void msgDisplay(String msg) {
textView.setText("Server - " + msg);
}
We have used handler because we cannot touch user interface from inside runnable in this case.
Thanks
Figured this out ....
On the client side I was using outputStream.write(...) to send the request to the server as in:
String syncReq = "Request to server.";
OutputStream outputStream = socket.getOutputStream();
outputStream.write(syncReq.getBytes());
But reading it on the server with BufferedReader.readLine():
Socket socket = mServer.accept(); //Block to receive message //
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.i(TAG, "Message received! " + in.readLine());
My problem was that outputStream.write(...) does not append a '\n' at the end of the String, but in.readLine() on the server expects it. Therefore the server was blocking while waiting for '\n'; which in turn caused the client socket to timeout.
I am developing a android wifi -chat application .
Bit of Info about my app :
->A device calls startserver() to act as a server ,another device calls start client() to act as a client
What works:
->A Client can successfully send the data for the first time to the client, but not again and again
->I need to call startserver() again on first device , so that client can send data again .
The startserver() calls this Async task ,the following is its DoinBackgroundMethod
protected String doInBackground(Void... params) {
ServerSocket serverSocket = null;
try {
while(true) {
serverSocket = new ServerSocket(PORT);
Socket client = serverSocket.accept();
StartMSG(client);
}
} catch (IOException e) {
return null;
} finally {
try {
chatclient.changeserverrunning(false);
if (serverSocket == null) {
} else {
serverSocket.close();
}
return null;
} catch (Exception e) {
}
}
//return null;
}
protected void StartMSG(Socket client){
try {
InputStream inputstream = client.getInputStream();
ObjectInputStream ois = new ObjectInputStream(inputstream);
Message m = null;
try {
m = (Message) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (m != null) {
if (m.gettype() == 1) {
final String my_msg = m.getMessage();//Toast msg afterwards
}
}catch (Exception e){
}
}
Client Side Code :
It is started when the client hits send button and calls start client method .in which It sets up the Ip values before and bundles them and calls the message sending part as a Intent Service called FileTransferService
Its code is (abstracted) :
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
if(socket==null){
socket = new Socket();
}
if (intent.getAction().equals(ACTION_SEND_FILE)) {
final String msg_type=intent.getExtras().getString(MESSAGE_TYPE);
String host = intent.getExtras().getString(EXTRAS_ADDRESS);
int port = intent.getExtras().getInt(EXTRAS_PORT);
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Message m = (Message) intent.getExtras().getSerializable(MESSAGE_INTENT_STR);
final String my_message=m.getMessage();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(m);
oos.flush();
oos.close();
InputStream is = new ByteArrayInputStream(baos.toByteArray());
OutputStream stream = socket.getOutputStream();
ChatClient.copyFile(is, stream);
} catch (IOException e) {
} finally {
if (socket != null) {
if (socket.isConnected()) {
try {
//socket.close();
} catch (Exception e) {
// Give up
e.printStackTrace();
}
}
}
}
}
}
You should try https://github.com/tavendo/AutobahnAndroid and run the client from a service, from an asyntask it will always end up finishing.
I'm trying to create a proxy in Android and I have to use sockets . I've read many tutorials and came up with following code. Unfortunately browser doesn't seem to get any data and after some time it displays standard web page saying that web page is not available. What might be the cause? Thanks for your help.
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(9902, 0, InetAddress.getByName("localhost"));
} catch (Exception e) {
e.printStackTrace();
}
if (serverSocket != null) {
while (!Thread.currentThread().isInterrupted()) {
try {
Socket socket = serverSocket.accept();
new Thread(new RunnableToReadSocketData(socket)).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private class RunnableToReadSocketData implements Runnable {
private final Socket clientSocket;
public RunnableToReadSocketData(Socket socket) {
this.clientSocket = socket;
}
#Override
public void run() {
Socket serverSocket = null;
try {
InputStream streamFromClient = clientSocket.getInputStream();
PrintWriter streamToClient = new PrintWriter(clientSocket.getOutputStream());
StringWriter writer = new StringWriter();
IOUtils.copy(streamFromClient, writer);
String requestString = writer.toString();
int firstSpace = requestString.indexOf(" ");
int secondSpace = requestString.indexOf(" ", ++firstSpace);
String url = requestString.substring(firstSpace, secondSpace);
Uri uri = Uri.parse(url);
String urlWithoutProtocol = uri.getHost();
System.out.println("==============Reading Socket==============\n" + clientSocket.toString() + "\n" + requestString);
serverSocket = new Socket(urlWithoutProtocol, 80);
PrintWriter streamToServer = new PrintWriter(serverSocket.getOutputStream(), true);
streamToServer.write(requestString);
streamToServer.flush();
InputStream streamFromServer = serverSocket.getInputStream();
StringWriter writerResponse = new StringWriter();
IOUtils.copy(streamFromServer, writerResponse);
String responseString = writerResponse.toString();
System.out.println("==============RECEIVED==============\n" + serverSocket.toString() + "\n" + responseString);
streamToClient.write(responseString);
streamToClient.flush();
streamToClient.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
if (clientSocket != null) {
clientSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You're doing this wrong. After you process the CONNECT command you need to start two threads to copy bytes over the connection, one in each direction. Don't attempt to read the entire request before you send anything; ditto the response. Just copy bytes as you receive them.
When you read EOS on one socket, shutdown the other socket for output and exit that thread. If you've already shutdown the socket you read the EOS from, close both and exit the thread. You need this in case either end does a shutdown, to propagate it properly.
I agree with previous.
The general principle is:
Client connects
Start reading thread
Receive request
Parse destination
Open socket to destination
Forward request
For every Read on the destination socket, do a write on the client socket
For every Read on client socket, do a write on destination socket
If either socket closes (errors), close the other
So, two InputStream's, two OutputStreams, and just ferry data across them.
Hey community I have the following ServerSocket which should listen to port 53000 and log any received data. However, I cannot seem to get past the server.accept() blocking call.
public void run() {
SocketServer server = new ServerSocket(53000);
//---buffer store for the stream---
byte[] buffer = new byte[1024];
//---bytes returned from read()---
int bytes;
//---keep listening to the InputStream until an
// exception occurs---
while (true) {
try {
socket = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = in.readLine();
Log.i("received response from server", str);
in.close();
socket.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} catch (Exception e){
server.close();
Log.e(TAG, e.getMessage());
}
}
}
I have also given the application the INTERNET permission in the Manifest file.
()
To add to the mystery, I have also verified client responses get sent to that port.
Is there something in particular I need to do to make this work?
Thanks.
Your code is very messy and won't even compile. I made some adjustments so that i could test your code, and it's working fine. Here is the test application I used:
package com.test.stackoverflow
import java.io.BufferedReader;
public class ServerSocketTestActivity extends Activity {
/** Called when the activity is first created. */
private static String TAG = "ServerSocketTest";
private ServerSocket server;
Runnable conn = new Runnable() {
public void run() {
try {
server = new ServerSocket(53000);
while (true) {
Socket socket = server.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String str = in.readLine();
Log.i("received response from server", str);
in.close();
socket.close();
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(conn).start();
}
#Override
protected void onPause() {
super.onPause();
if (server != null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Using this code and netcat running via adb shell I was able to connect and communicate with the application.
When working with The Client Declare these methods
To access Streams
// gets the input stream // ObjectInputStream input;
// gets the output stream // ObjectOutputStream output;
// ServerSocket server;
// Socket connection;
maybe you have a another class to access the socket;
server = new ServerSocket(5001, 100);
// step 1 create socket connection
server = new ServerSocket(5001, 100);
while(the condition is true)
// step 2 wait for connection
// step 3 get streams
// step 4 : process the connection
// step 5 : close connection
I have a BufferedReader, when I try to read it, it just hangs and doesn't do anything, am I doing this right? I am using this in an AsyncTask.
Edit: I have a tablet connected to the Wi-Fi, this connects to my computer which is broadcasting on 172.20.104.203 on port 5334, I can see when the thread starts, but nothing after that.
Here my code:
try {
final BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
final String msg;
msg = (line);
Log.d("DeviceActivity", msg);
}
} catch (Exception e) {
e.printStackTrace();
Log.e("ClientAcivtity: Exception",
String.valueOf(e));
}
EDIT
I have all the right permissions or anything, I was doing this outside a AsyncTask and it worked perfectly, moved it because I didn't want it in the main thread.
-Edit , here is the full code.
public class NetworkTask extends AsyncTask<Void, byte[], Boolean> {
Socket nsocket; // Network Socket
InputStream nis; // Network Input Stream
OutputStream nos; // Network Output Stream
private Handler handler = new Handler();
Boolean connected = false;
public static final int PORT = 5334;
public String SERVERIP = "172.20.104.203";
Socket socket;
#Override
protected void onPreExecute() {
Log.i("AsyncTask", "onPreExecute");
InetAddress serverAddr;
try {
serverAddr = InetAddress.getByName(SERVERIP);
socket = new Socket(serverAddr, PORT);
connected = true;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("ClientAcivtity: Exception", String.valueOf(e));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("ClientAcivtity: Exception", String.valueOf(e));
}
}
#Override
protected Boolean doInBackground(Void... params) { // This runs on a
// different thread
boolean result = false;
try {
Log.d("ClientActivity", "C: Connecting...");
if (socket != null) {
int cont = 1;
while (cont == 1) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
// where you issue the commands
out.println("getPos");
Log.d("ClientActivity", "C: Sent " + "getPos");
} catch (Exception e) {
Log.e("ClientAcivtity: Exception",
String.valueOf(e));
}
try {
final BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
final String msg;
msg = (line);
Log.d("DeviceActivity", msg);
}
} catch (Exception e) {
e.printStackTrace();
Log.e("ClientAcivtity: Exception",
String.valueOf(e));
}
cont--;
}
Log.d("ClientActivity", "C: Closed.");
}
} catch (Exception e) {
Log.e("ClientAcivtity: Exception", String.valueOf(e));
}
return result;
}
#Override
protected void onProgressUpdate(byte[]... values) {
if (values.length > 0) {
Log.i("AsyncTask", "onProgressUpdate: " + values[0].length
+ " bytes received.");
}
}
#Override
protected void onCancelled() {
Log.i("AsyncTask", "Cancelled.");
}
#Override
protected void onPostExecute(Boolean result) {
if (socket != null) {
if (connected) {
if (result) {
Log.i("AsyncTask",
"onPostExecute: Completed with an Error.");
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Log.i("AsyncTask", "onPostExecute: Completed.");
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
My guess is that when you write out the command "getPos" the underlying BufferedWriter is not actually sending the data out on the line (you should verify this with tcpdump/wireshark). If this is the case, the server doesn't responsed to the readLine(), since it never got a command. To verify this claim, add out.flush(); after out.println("getPos");
Really, tcpdump will probably give you a better answer then anyone on the forums.
Also see http://developer.android.com/reference/java/io/BufferedWriter.html
Try doing it like this:
final BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
StringBuffer buf = new StringBuffer();
int i;
while((i = in.read()) != -1){
buf.append((char) i);
}
String data = buf.toString();
Reading from sockets is a quite difficult issue depending where the socket is actually connected to and how the other side responds.
If the other side is extremely fast than it can provide the socket with enough data so that the read routines actually work fine. However if there is a delay in the other side of any kind (just needs to be slower than your read routine incl the small default timeout) then your read fails even though there might be data on the other side - just arriving a little too slow at the socket.
Depending on your needs you may wrap your own minimum and maximum timer around the read routine.
Please provide more information and we can better understand the issue.
In many cases it is necessary to have a minimum timeout large enough for the other side to push data to the socket - but you might also need a maximum time for how long you actually want to wait for data to arrive.
UPDATE:
first the runnable to start the monitoring thread. You may use monitoringCanRun in your loop to interrupt the thread if required. And monitoringThreadIsAlive can be used to know if the thread is still running.
monitoringCanRun = true;
new Thread(new Runnable() {
public void run() {
monitoringThreadIsAlive = true;
performMonitoring();
monitoringThreadIsAlive = false;
}
}).start();
}
and performMonitoring looks like:
public void performMonitoring() {
while (monitoringCanRun) {
... do your read in the while loop
...you might like to insert some delay before trying again...
try { //we delay every partial read so we are not too fast for the other side
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}