First of all, I'm not a C# programmer, so please forgive me for copy pasting a C# socket client from MSDN examples page.
Basically, if you want to communicate over USB with Android application, you need to instruct your phone to create port forwarding via adb
(Android Debug Bridge), and then you can use normal TCP/IP sockets to establish stream communication with your client.
So first, you have to have proper drivers installed on your PC (you can find them on your manufacturers web site), so that when you run adb devices
, your phone is correctly identified:
C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb devices
List of devices attached
039d78fa2518e606 device
Next thing you need is to setup port forwarding on the Android side, so that socket connections on/to your localhost on your PC will be properly forwarded to the localhost on the phone. This is also done via adb
:
C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb forward tcp:6000 tcp:6000
Verify that it was successfull:
C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb forward --list
039d78fa2518e606 tcp:6000 tcp:6000
And now you can create a regular socket server application on the Android side. I apologize that this example is very simple (I noticed this question very late and didn't have time to implement proper communication protocol). But this should show you how to transfer strings between client and host, and you can implement necessary loops, or more complicated transfer protocols if needed.
Basically this is just the default Android project, with 1 added class, that is run in a separate thread (GUI and network activities cannot be run in same thread).
So, our MainActivity.java looks like this:
package com.example.dataexchange;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
public class MainActivity extends ActionBarActivity {
SocketHandler server;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.v("jlumme", "Main/ start network task");
new Thread(new Runnable() {
public void run() {
server = new SocketHandler(6000);
server.run();
}
}).start();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
The usual stuff, we just start our SocketHandler
class in a separate thread. The SocketThread class looks like this:
package com.example.dataexchange;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import android.util.Log;
public class SocketHandler implements Runnable {
private Socket socket;
private ServerSocket server;
private PrintWriter out;
private BufferedReader in;
private int socketPort;
SocketHandler(int port) {
socketPort = port;
}
@Override
public void run() {
Log.v("jlumme", "Socket thread has started");
String inputText;
// TODO Auto-generated method stub
try {
Log.v("jlumme", "Starting socket server ");
server = new ServerSocket(6000);
socket = server.accept();
Log.v("jlumme", "Client connected");
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((inputText = in.readLine()) != null) {
Log.v("jlumme", "Received:" + inputText);
out.println("you wrote:" + inputText);
}
Log.v("jlumme", "connection established");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Basically in the run()
method you start a new SocketServer
, and start waiting for clients. Once a client connects, you setup stream buffers both ways, and start waiting for a message (anything ending with a line break, '\n'
will do).
On the C# side, the application is very simple. It connects to localhost
port 6000
and sends one line:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class SynchronousSocketClient
{
public static void StartClient() {
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try {
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Connect the socket to the remote endpoint. Catch any errors.
try {
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes("This is a test\n");
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes,0,bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
} catch (SocketException se) {
Console.WriteLine("SocketException : {0}",se.ToString());
} catch (Exception e) {
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
} catch (Exception e) {
Console.WriteLine( e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
return 0;
}
}
If when execute the C# program, it will send this is a test
string to the client, and client will echo it back:
c:\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\bin\Debug>ConsoleApplication2.exe
Socket connected to 127.0.0.1:6000
Echoed test = you wrote:This is a test
I wanted to reach the deadline before bounty closes, so currently there is no proper message handling, and c# will exit immediately (while Android side will get confused by this), I apologize for that. But I think once you get this example running, you can easily extend it to your needs, and implement necessary logic to handle terminations and other stuff..
Hope it helps
C#
should poll forNFC messages received
to the connected android devices, or the android device connected shouldsend data
to thec# program
once itreceives an NFC message
sir.. :) will that be possible? do you have an idea on how to do this? – Hasitha Shan