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.
Related
Is there any good option to send broadcast message on UDP port while receiving data from other devices on the same port?
I have this currently:
First I initialize 1 DiagramSocket for both reading and sending:
private void startSocket(){
try {
if(socket == null) {
socket = new DatagramSocket(3040);
socket.setBroadcast(true);
socket.setReuseAddress(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
In first Thread I have reading/receiving for current socket:
public class Server implements Runnable {
public Server(iBroadcastResponse iBResponse){
BroadcastClass.this.iBResponse = iBResponse;
}
#Override
public void run() {
startSocket();
while (DataHandler.isEmergencyMode.get() ) {
try {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
if(socket == null)
return;
socket.receive(packet);
String command = stringFromPacket(packet);
Log.d(TAG, command);
addToBroadcastCalls(command);
if(iBResponse != null)
iBResponse.onResponse();
} catch (Exception e) {
Log.e(TAG, "Server: Error!\n");
}
}
Log.e(TAG, "Stop!");
}
String stringFromPacket(DatagramPacket packet) {
return new String(packet.getData(), 0, packet.getLength());
}
}
If I run this, it works normally, reads receiving data. But if I try to send data in another thread:
socketThread = new Thread(){
#Override
public void run() {
startSocket();
String message = "Message";
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
if(!socket.isConnected())
socket.connect(InetAddress.getByName("255.255.255.255"), 3040);
if (socket != null) {
socket.send(packet);
}
Log.d(TAG, "Send: " +message);
} catch (Exception e) {
e.printStackTrace();
}
}
};
socketThread.start();
When .send() is called it stops receiving data from other devices so now it only send message but stops receiving it from other devices.
Is there any good solution to this problem?
This was the solution
https://stackoverflow.com/a/25520279/1088975
I only changed
System.log...
To
Log.w(TAG, "Message...");
And I changed IP to be always "255.255.255.255" instead of
getBroadcastAddress()
which returns broadcast IP for current WIFI, which didn't work on my android devices
i am making a chat application for android using UDP.
Everything works fine in lan devices, I can send and receive messages from client and from server.
When i connect to an other network with my android, i can send messages, the server receives them but the response is never received on android.
Client Receive code
Runnable periodicTask = new Runnable() {
public void run() {
// Invoke method(s) to do the work
System.out.println("Waiting for data");
byte[] receiveData = new byte[2028];
byte[] sendData = new byte[2028];
boolean portTaken=false;
DatagramSocket serverSocket=null;
ServerSocket socket = null;
try {
socket = new ServerSocket(6667);
} catch (IOException e) {
System.out.println("ERRORRRRRRRRRRRRRR");
} finally {
if (socket != null)
try {
socket.close();
serverSocket= new DatagramSocket(6667);
} catch (IOException e) { e.printStackTrace(); }
}
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
try {
serverSocket.receive(receivePacket);
System.out.println("GOT THEM!");
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream in = new ByteArrayInputStream(receiveData);
ObjectInputStream is = null;
try {
is = new ObjectInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
Data student = null;
try {
student = (Data) is.readObject();
l.add(student.toString());
mHandler.sendEmptyMessage(0);
System.out.println(student);
serverSocket.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
Server Send Code
for (DatagramPacket packet:clients){
if (!packet.getAddress().equals(receivePacket.getAddress())){
System.out.println("current ip address " + receivePacket.getAddress());
System.out.println("Sending to " + packet.getAddress());
DatagramSocket s = new DatagramSocket();
InetAddress local =packet.getAddress();//editTextAddress.getText().toString());//InetAddress.getByName("192.168.1.74");
System.out.println(local.toString());
//int msg_length =student.//sentence.length();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(outputStream);
os.writeObject(student);
byte[] data2 = outputStream.toByteArray();
int msg_length =data2.length;
DatagramPacket p = new DatagramPacket(data2, msg_length, local,
6667);
s.send(p);
s.close();
}
What might be the case ?
Thank you for your time
I tested many ways and finally asked this question. as many of articles mentioned in wifi-direct all clients know group owner's IP and can use this ip to send a message and group owner will save clients ip address. but I can't send a message from group owner to client like that client sent first time. I faced with this error's:
first:
failed to connect to /192.168.49.24 (port 8988) after 5000ms: isConnected failed:
EHOSTUNREACH (No route to host).
after change code:
first error + bind failed: EADDRINUSE (Address already in use).
My AsyncTask to retrieve :
#Override
protected String doInBackground(Void... params) {
ServerSocket serverSocket = null;
Socket client = null;
DataInputStream inputstream = null;
try {
serverSocket = new ServerSocket(8988);
client = serverSocket.accept();
inputstream = new DataInputStream(client.getInputStream());
String str = inputstream.readUTF();
String IP = client.getInetAddress().toString();
serverSocket.close();
return IP+"+"+str;
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
return null;
}finally{
if(inputstream != null){
try{
inputstream.close();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
}
}
if(client != null){
try{
client.close();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
}
}
if(serverSocket != null){
try{
serverSocket.close();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
}
}
}
}
and my IntentService to send messages:
#Override
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
if (intent.getAction().equals(ACTION_SEND_IP)) {
String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
Log.e("DAVUD","Host:"+ host);
Socket socket = new Socket();
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
Log.e("DAVUD","Port:"+ port);
DataOutputStream stream = null;
try {
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
stream = new DataOutputStream(socket.getOutputStream());
String str = intent.getStringExtra("message");
stream.writeUTF(str);
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
and some other codes I tested... There is another question asked same this but not answered(android-wifi-direct-how-to-send-data-from-group-owner-to-the-clients) this project based on wifiDirectDemo Simple. Please help I really need it.
After one year I sew my question again. the problem was not about wifi or connection. it's about string parsing. where a line in doInBackground is:
return IP+"+"+str
and in onPostExecute I parsed and get ip from returned string; but parse code was not correct. so returns:
192.168.49.24
instead of:
192.168.49.241
where two of them is valid ips I am not thought parse logic had problem. I changed code and used String[] instead of String.
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
I'm making an app that sends a string to a server over a socket and then reads the output after the server has processed that data. It worked perfectly when it was my foreground task, but I have since used AsyncTask to show a process dialog while the socket communication runs in the background, and things start breaking after I read the output from the server and then try to close the socket.
private class Progressor extends AsyncTask<String, Void, Void> {
ProgressDialog dialog;
protected void onPreExecute() {
dialog = ProgressDialog.show(ClearTalkInputActivity.this, "Loading..", "Analyzing Text", true, false);
}
protected Void doInBackground(String... strings) {
String language = strings[0].toLowerCase();
String the_text = strings[1];
Socket socket = null;
DataOutputStream dos = null;
DataInputStream dis = null;
try {
socket = new Socket(my_ip, port);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
dos.writeUTF(language+"****"+the_text);
String in = "";
while (in.indexOf("</content>") < 0) {
in += dis.readUTF();
}
socket.close();
save_str(OUTPUT_KEY, in);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute() {
if (dialog.isShowing())
dialog.dismiss();
startActivity(new Intent (output_intent));
}
}
The recommended way in Android is to use one of the two included HttpClients:
Apache HTTP Client
HttpURLConnection
There is no need to use sockets directly. These clients do a lot to improve your experience.
Here is a blog article by the Android developers, that explain the basics: http://android-developers.blogspot.de/2011/09/androids-http-clients.html