Communication on 2 ports between 2 Android devices using WiFi Direct - android

I am creating an application that will monitor movements in a particular Android device (client) and report such instances to another Android device (server). Also, under specific conditions, the client will take a picture and transmit the image to the server.
I am using WiFi direct to setup the connection between the two devices. After that I am using socket connections as explained in the WiFi Direct Demo. I am using port 8988 to send the motion sensor events and I am using port 8987 to send the images capture.
On the server side, I am using two different instances of the same Async Task with serversocket connecting to different ports to listen for the incoming messages. Everything works fine as long as only the motion sensor events are being sent across. The first image capture is also being sent/received correctly. However, after that the server doesn't receive any additional messages. I tried having two different Async Task classes to avoid having two instances of the same class but that didn't work as well. I also tried having one as an Async Task and another as an Intent Service but even that doesn't work.
This is IntentService I am using to send the messages across to the server.
public class MessageSender extends IntentService {
public static final String EXTRAS_TIMEOUT = "timeout";
public static final String EXTRAS_ADDRESS = "go_host";
public static final String EXTRAS_PORT = "go_port";
public static final String EXTRAS_DATA = "data";
private Handler handler;
public MessageSender(String name) {
super(name);
}
public MessageSender() {
super("MessageTransferService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
String host = intent.getExtras().getString(EXTRAS_ADDRESS);
Socket socket = new Socket();
int port = intent.getExtras().getInt(EXTRAS_PORT);
byte[] data = intent.getExtras().getByteArray(EXTRAS_DATA);
int timeout = intent.getExtras().getInt(EXTRAS_TIMEOUT);
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), timeout);
OutputStream stream = socket.getOutputStream();
stream.write(data);
} catch (final IOException e) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Exception has occurred: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
} finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
/*handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Socket Connection closed now..",
Toast.LENGTH_SHORT).show();
}
});*/
} catch (IOException e) {
// Give up
e.printStackTrace();
}
}
}
}
}
}
This is Async Task on the server that starts listeners on two ports (8987 and 8988) to receiver the information of motion sensor events and images.
public class MessageReceiver extends AsyncTask<Void, Void, String> {
private Context context;
private int port;
private Bitmap mBitmap;
public MessageReceiver(Context context, int port) {
this.context = context;
this.port = port;
}
#Override
protected String doInBackground(Void... params) {
try {
ServerSocket serverSocket = new ServerSocket(port);
Socket client = serverSocket.accept();
InputStream inputstream = client.getInputStream();
String returnString = "";
if (port == MainActivity.PORT_SENSOR_COMM) {
// do something
} else if (port == MainActivity.PORT_IMAGE_COMM) {
//do something
}
serverSocket.close();
return returnString;
} catch (Exception e) {
return "Exception Occurred:" + e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
boolean startNewTask = true;
if (port == MainActivity.PORT_SENSOR_COMM) {
//do something
} else if (port == MainActivity.PORT_IMAGE_COMM) {
//do something
}
//doing this to start listening for new messages again
new MessageReceiver(context, port).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
#Override
protected void onPreExecute() {
}
}
I am now wondering whether Android WiFiDirect allows parallel communication between two devices on different ports. Searched the docs but could'nt find much help. What I am doing wrong? What is the correct method to accomplish what I am trying to do? Any help would be greatly appreciated. Thanks for looking.

Related

How to send hard coded string from Android APP when button is pressed to a UDP listener in Node-Red?

OVERVIEW
I'm using Android Studio to make an app that on a button press sends a string to a UDP listener in Node-Red running on my laptop, Node-Red filters anything that comes in and function nodes do their thing. This app will work inside a LAN not over the internet.
So far I have made a new project with an empty activity and my activity_main.xml has the button. There is no need for the user to input a string/text so the button press code will have the "string" and Node-Red listener IP and port hard coded.
There is also no need to receive a reply from the laptop/node-red side so the button press should be a fire and forget hard coded message hence UDP and not a TCP socket.
QUESTION
What code is required for the MainActivity to send the string when the button is pressed to the UDP listener in Node-Red?
I have spent a long time scouring the internet for answers and tried many code examples however they have not worked. A lot of the research I've seen is people with UDP receive problems, however I cannot understand their code for sending UDP.
I finally worked it out with a ridiculous amount of trial and error... please see the code below if anyone else ever gets the same problem:
//On button press the message is sent via UDP
findViewById(R.id.btSendMessage).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int txnumber = Integer.parseInt(((TextView) findViewById(R.id.transmitnumber)).getText().toString());
String data = ((TextView) findViewById(R.id.texttosend)).getText().toString();
int port = Integer.valueOf(((TextView) findViewById(R.id.serverport)).getText().toString());
String address = ((TextView) findViewById(R.id.serverip)).getText().toString();
SendData(txnumber, data, port, address);
}
});
private DatagramSocket UDPSocket;
private InetAddress address;
private int port;
public void Theaddress(InetAddress address) {
try {
this.UDPSocket = new DatagramSocket();
this.address = address;
} catch (SocketException e) {
e.printStackTrace();
}
}
public void SendInstruction(final byte[] data, final int port) {
new Thread() {
#Override
public void run() {
try {
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
UDPSocket.send(packet);
DatagramPacket packetreponse = null;
UDPSocket.receive(packetreponse);
DisplayData(packetreponse);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public void SendData(final int nbRepet, final String Sdata , final int port, final String address) {
new Thread() {
#Override
public void run() {
try {
Theaddress(InetAddress.getByName(address));
for (int i = 0; i < nbRepet; i++) {
byte[] data = Sdata.getBytes();
SendInstruction(data,port);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public void ReceiveData(final int portNum) {
new Thread() {
#Override
public void run() {
try {
final int tally = 1024;
final byte[] buffer = new byte[tally];
DatagramSocket socketReceive = new DatagramSocket(portNum);
while (true) {
DatagramPacket data = new DatagramPacket(buffer, buffer.length);
socketReceive.receive(data);
DisplayData(data);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public void DisplayData(DatagramPacket data) {
System.out.println(data);
}

How can I connect two Android device by socket without server

I am trying to develop an android application that can exchange data on peer to peer connection with other devices without server. So please suggest how can I do this. Thank you in advance.
This is a complete code for chat by SocketProgramming without server.
In my Application, first you are a client and you search for a server. When you do not find any server, you become a server and wait for a client.
public class MainActivity extends ActionBarActivity {
private Handler handler = new Handler();
private TextView text;
private EditText input;
private Button send;
private Socket socket;
private DataOutputStream outputStream;
private BufferedReader inputStream;
private String DeviceName = "Device";
private boolean searchNetwork() {
log("Connecting");
String range = "192.168.56.";
for (int i = 1; i <= 255; i++) {
String ip = range + i;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip, 9000), 50);
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
DeviceName += "1";
Log.i("Server", DeviceName);
log("Connected");
return true;
} catch (Exception e) {
}
}
return false;
}
private void runNewChatServer() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(9000);
log("Waiting for client...");
socket = serverSocket.accept();
DeviceName += "2";
log("a new client Connected");
} catch (IOException e) {
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
input = (EditText) findViewById(R.id.input);
send = (Button) findViewById(R.id.send);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
if (!searchNetwork()) {
runNewChatServer();
}
outputStream = new DataOutputStream(
socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while (true) {
String Message = inputStream.readLine();
if (Message != null) {
log(Message);
}
}
} catch (IOException e) {
log("Error: IO Exception");
e.printStackTrace();
}
}
});
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (outputStream == null) {
return;
}
try {
String Message = input.getText().toString() + "\n";
outputStream.write(Message.getBytes());
log2(input.getText().toString());
} catch (IOException e) {
e.printStackTrace();
}
input.setText("");
}
});
thread.start();
}
private void log(final String message) {
handler.post(new Runnable() {
String DeviceName2="";
#Override
public void run() {
if (DeviceName.equals("Device1")) {
DeviceName2 = "Device2";
}else if(DeviceName.equals("Device2")) {
DeviceName2 = "Device1";
}else{
DeviceName2 = "UnknowDevice";
}
text.setText(text.getText() + "\n" + DeviceName2 + " :"
+ message);
}
});
}
private void log2(final String message) {
handler.post(new Runnable() {
#Override
public void run() {
text.setText(text.getText() + "\n" + "you" + " :"
+ message);
}
});
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.exit(0);
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Your design has a big problem : ...
If there is no central server some android devices should act as client and others as server but this will not work in some situations:
When the mobile telephony provider assigns private and non-public IP
When the device is connected to a Wi-Fi network but no NAT rule is defined on the router.
In both cases the problem is that the listening port of the device that must act as server is unreachable.
Java provides ServerSocket and Socket to communicate b/w devices. One of the device you can make as server and other device you can make as client and communicate b/w 'em without introducing server hosted on some machine.
The Other and better option is Using Wi-Fi Peer-to-Peer. WifiP2pManager help you to achieve your purpose.Here is an example.
If you're looking for such P2P over a local network, there are two parts to it:
Discovering peers
Communicating with peers
Among Android APIs, you can either use Network Service Discovery APIs for this or Wifi P2P Service Discovery APIs.
There's a wrapper library which which uses these internally and has comparatively better documentation - Salut, which can also be used.
I also created a library for P2P - Near, which uses sockets directly. The problem I was facing with Android APIs was that discovery wasn't happening with certainty every time and the underlying issue was unknown.
If you're looking for P2P across the internet, socket IO is a prevalent solution. Even Near should be able to facilitate the transfers if you provide the IP addresses and they're not behind NAT firewalls.

Android socket still can write without exception when wifi has been disconnected

I write an Android socket demo which just post user's input to server.
I establish a socket from android client through wifi connection, and everything goes well, the server can receive the message send from android client. The problem is, then I close WIFI of phone, but the socket can write without exception.
The code of Android client:
public class MyActivity extends Activity {
private SocketHandlerThread thread;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
thread = new SocketHandlerThread("ScoketTest");
thread.start();
}
class SocketHandlerThread extends HandlerThread {
private Socket socket;
private Handler handler;
public SocketHandlerThread(String name) {
super(name);
}
public SocketHandlerThread(String name, int priority) {
super(name, priority);
}
#Override
public void run() {
try {
socket = new Socket("192.168.60.184", 1990);
} catch (IOException e) {
Log.e("SocketTest", e.getLocalizedMessage(), e);
}
super.run();
}
Handler getHandler() {
if (handler == null) {
handler = new Handler(getLooper());
}
return handler;
}
void send(final String text) {
Runnable runnable = new Runnable() {
public void run() {
Log.e("SocketTest", "Start send text: " + text);
try {
socket.getOutputStream().write((text + "\n").getBytes());
socket.getOutputStream().flush();
} catch (Exception e) {
Log.e("SocketTest", e.getLocalizedMessage(), e);
}
Log.e("SocketTest", "Text has been send:" + text);
}
};
getHandler().post(runnable);
}
#Override
protected void onLooperPrepared() {
runOnUiThread(new Runnable() {
#Override
public void run() {
findViewById(R.id.button).setEnabled(true);
}
});
}
}
public void send(View view) {
String text = ((EditText) findViewById(R.id.text)).getText().toString();
thread.send(text);
}
}
The code of Server:
public class SocketTestServer {
ServerSocket serverSocket;
SocketTestServer() throws IOException {
serverSocket = new ServerSocket(1990);
}
void start() throws IOException {
Socket clientSocket = serverSocket.accept();
clientSocket.getInputStream();
PrintWriter out = new PrintWriter(System.out, true);
BufferedReader in =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
}
public static void main(String[] args) throws IOException {
SocketTestServer server = new SocketTestServer();
server.start();
}
}
I try on several phones. On Galaxy Nexus(4.2.1) an exception was thrown as expected, but on some MOTO or HTC phones socket can still write without any exception, which means I may loss some messages that I thought has been received successfully.
How could I get known that the socket connection was broken on any type of phone?
Any suggestion will be appreciated.
p.s
I know the Connective Change Broadcast, but before receive the broadcast the client may have write some message through the broken socket.
Though adding receive check on application protocol can solve the message lossing problem, I prefer to guarantee reliability on transport layer which the TCP protocol promise to do.
I use Writer & IOException in my socket, it works fine. Try this:
public static void sendUTF(String str)
{
try
{
outWriter.write(str + '\n');
outWriter.flush();
}
catch (IOException e)
{
e.printStackTrace();
outServ.setText("Connection lost!");
}
}
public static Writer outWriter = new OutputStreamWriter(outputStream, "UTF-8");
This is a problem with the TCP stack (OS level) and is a problem difficult to solve.
It happens also if the server is the one which lose connection (try to restart your server after opening the socket and no client will notice)... you will suffer a "broken pipe error" next time you send a packet through the socket.
So, there are two scenarios:
1- broken pipe when client sends information.
In this scenario you should capture the IOException and retry to open the connection (you will have to define your retry policies).
2- broken pipe when the server lose connectivity
When the server lose connection the client doesn't notice so, In this scenario you should send packets to the server in a regular basis (polling technique) and try to reconnect just in case the connection is lost.
This is needed just if you receive from the server updates, if you traffic is always client-->server only the scenario 1 applies.

Communicate worker thread with main thread

I'm developing an Android application.
This application will have a server to start a DatagramSocket as a server. It will wait for incoming message. When the socket get a message I will process it.
To start a UDP Server socket I'm going to use a Local Service. This service will have a worker thread where I'm going to listen to incoming messages.
This is my unfinished Local Service implementation:
public class UDPSocketBackgroundService extends Service
{
private static final String TAG = "UDPSocketBackgroundService";
private ThreadGroup myThreads = new ThreadGroup("UDPSocketServiceWorker");
private Handler mServiceHandler;
#Override
public void onCreate()
{
super.onCreate();
Log.v(TAG, "in onCreate()");
}
#Override
public IBinder onBind(Intent arg0)
{
try
{
new Thread(myThreads, new UDPServerThread("X", 8888)).start();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
And this is my also unfinished Worker Thread implementation:
public class UDPServerThread extends Thread
{
private static final int MESSAGE_SIZE = 256;
protected DatagramSocket socket = null;
protected boolean end = false;
public UDPServerThread(String serverName, int port) throws IOException
{
super(serverName);
socket = new DatagramSocket(port);
}
public void run()
{
while (!end)
{
try
{
byte[] buf = new byte[MESSAGE_SIZE];
// Wait an incoming message.
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// TODO: Notify Service with packet received
}
catch (IOException e)
{
// TODO Mensaje de error.
e.printStackTrace();
}
}
}
}
Those classes have their own file (they are on different files).
Here:
socket.receive(packet);
//TODO: Notify Service with packet received
How can I notify service that we have received a packet? I want to send to service that packet also.
Here there is an example on how to communicate from Main thread to worker thread. But, I don't need that, I'm looking for an example on how to communicate from worker thread to service.
I've found this example, but I don't understand it very well because on that example both classes are declare it on the same file.
As you can see, I'm a newbie on Android development.
If you know a better approach, please tell me.
When you create the UDPServerThread, you could pass in a reference to the UDPSocketBackgroundService and then call a method on it (processPacket() for example) when packets are received. This processPacket() method will need to use some sort of synchronization.
Here's a small code excerpt of the related functions:
public class UDPSocketBackgroundService extends Service
{
....
#Override
public IBinder onBind(Intent arg0)
{
try
{
new Thread(myThreads, new UDPServerThread(this, "X", 8888)).start();
// Notice we're passing in a ref to this ^^^
}
...
}
public void processPacket(DatagramPacket packet)
{
// Do what you need to do here, with proper synchronization
}
}
public class UDPServerThread extends Thread
{
private static final int MESSAGE_SIZE = 256;
protected DatagramSocket socket = null;
protected boolean end = false;
protected UDPSocketBackgroundService = null;
public UDPServerThread(UDPSocketBackgroundService service, String serverName, int port) throws IOException
{
super(serverName);
this.service = service;
socket = new DatagramSocket(port);
}
...
public void run()
{
while (!end)
{
try
{
byte[] buf = new byte[MESSAGE_SIZE];
// Wait an incoming message.
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
service.processPacket(packet);
}
...
}
...
}
}
Notice that going this approach, the UDPSocketBackgroundService is now "tightly coupled" with the UDPServerThread. Once you get this working, you may consider refactoring it with a more elegant design where there is less coupling, but for now this should get you going :)

android asynchronous sockets (android app as server waiting for clients to connect)

im trying to implement a tcp socket connection between an android app (as server) and a java based client running on windows. (short version below, without code)
Im using some sensor listener to implement a game movement (everybody knows this sensor based movement of racing games.
Ive implemented a service for that purpose, which is started out of the first activity. This service is implemented as follows (im just pasting the relevant code snippets, not the whole class):
public class ServerService extends Service {
ConnectionHandler conHandler;
#Override
public void onCreate() {
startListener();
}
private void startListener() {
conHandler = new ConnectionHandler(this);
conHandler.execute();
}
private void sendMessage(String s)
{
conHandler.write(s);
}
public void messageNotify(String s) {
//Log.d("receivedMessage", s);
}
}
The ConnectionHandler class:
public class ConnectionHandler extends AsyncTask<Void, Void, Void>{
public static int serverport = 11111;
ServerSocket s;
Socket c;
ConnectionListening conListening;
ConnectionWriting conWriting;
DataOutputStream dos;
DataInputStream dis;
ServerService server;
public ConnectionHandler(ServerService server)
{
this.server = server;
}
#Override
protected Void doInBackground(Void... params) {
try {
Log.i("AsyncTank", "doInBackgoung: Creating Socket");
s = new ServerSocket(serverport);
} catch (Exception e) {
Log.i("AsyncTank", "doInBackgoung: Cannot create Socket");
}
try {
//this is blocking until client connects
c = s.accept();
Log.d("ConnectionHandler", "client connected");
dis = new DataInputStream(c.getInputStream());
dos = new DataOutputStream(c.getOutputStream());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
conWriting = new ConnectionWriting(this.c, this.dos);
conWriting.execute();
conListening = new ConnectionListening(this.c, this.dis, this.server);
if(this.c != null)
{
Timer timer = new Timer();
timer.schedule(conListening, 0, 10);
}
Log.i("AsyncTank", "doInBackgoung: Socket created, Streams assigned");
return null;
}
public void write(String s)
{
conWriting.writeToStream(s);
}
public void messageNotify(String s) {
// TODO method stub
}
}
The ConnectionHandler ist implemented as AsyncTask similarly to the ConnectionWriting, so that the blocking of tcp methods doenst affect the whole communication.
The client is able to send messages to the server to. Because i dont know when this messages will arrive, im using a TimerTask which is executed every 10ms, to check if there is a new message.
ConnectionWriting looks as follows:
public class ConnectionWriting extends AsyncTask<Context, Void, Boolean>{
public DataOutputStream dos;
Socket c;
public ConnectionWriting(Socket c, DataOutputStream dos) {
this.dos = dos;
this.c = c;
}
#Override
protected Boolean doInBackground(Context... params) {
return true;
}
public void writeToStream(String s) {
try {
if (c != null){
//Log.i("AsynkTask", "writeToStream");
dos.writeBytes(s+"\n");
dos.flush();
Log.i("AsynkTask", "write: " +s);
} else {
Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "writeToStream : Writing failed");
}
}
}
And the ConnectionListening class:
public class ConnectionListening extends TimerTask{
public DataInputStream dis;
Socket c;
ServerService server;
public ConnectionListening(Socket c, DataInputStream dis, ServerService server)
{
this.c = c;
this.dis = dis;
this.server = server;
}
#Override
public void run() {
String message = "";
try {
if (c != null) {
//Log.i("AsynkTask", "readFromStream : Reading message");
message = dis.readLine();
Log.i("AsynkTask", "read: " + message);
} else {
Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "readFromStream : Writing failed");
}
if(message != null)
{
this.server.messageNotify(message);
}
}
}
I choose this complex, asynchronous way because the server is almost continuous sending data to the client and there are situations where the client has to send data back.
With the traditional way of using tcp sockets, it is not possible to realise a non blocking communication, so that means if the server is sending (writing), the read function blocks and i will never get the client message.
to keep it short:
Ive tested my approach but the server is always sending his data first and then getting the client messages. It is not asynchronous!? :-/
Maybe anybody can help me to solve this problem.
Or is there even a simpler way to implement that approach?
It is necessary that the communication is asynchronous! And the read has to be done automatically (what i tried to implement with this polling approach).
Ive read that i can use a single thread for the reading and one for the writing, but then i have a problem with using the write functionality (dont know how to call a function in a running thread) and with calling functions in my activities.
Im thankful for every help!
regards

Categories

Resources