How to send a message from Android to Windows usin

2019-01-13 19:41发布

问题:

I am a complete noob at Android, only at the level of basic (1 or 2 line) Activities activated by buttons, but I would like to create a really simple app that, when I tap the app icon, it fires and forgets a message to a listening server on my Windows 8 PC. The phone is connected as a simple media device, without Kies, via a USB cable.

I can get as far as a message box lying and saying the message was sent. I need to know what kind of comms channel to use, e.g. a COM port or what, and how to send data over that from Android. On the Windows side, once I've established how to communicate, I can help myself.

回答1:

starting with the desktop side of this application: You can use the ADB (Android debug bridge) to establish a tcp/ip socket connection via port between the device and desktop. The command is :

adb forward tcp:<port-number> tcp:<port-number>

to run this command in your java program, you will have to create a process builder wherein this command ets executed on a child shell.

For windows you may need to use:

process=Runtime.getRuntime().exec("D:\\Android\\adt-bundle-windows-x86_64-20130729\\sdk\\platform-tools\\adb.exe forward tcp:38300 tcp:38300");
        sc = new Scanner(process.getErrorStream());
        if (sc.hasNext()) 
        {
            while (sc.hasNext()) 
                System.out.print(sc.next()+" ");
            System.out.println("\nCannot start the Android debug bridge");
        }
        sc.close();
        }

The function required to execute adb commands :

String[] commands = new String[]{"/bin/sh","-c", command};
        try {
            Process proc = new ProcessBuilder(commands).start();
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            String s = null;
            while ((s = stdInput.readLine()) != null) 
            {
                sb.append(s);
                sb.append("\n");
            }
            while ((s = stdError.readLine()) != null) 
            {
                sb.append(s);
                sb.append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

Above method will take the above command as a string and execute it on a child shell

  //Extracting Device Id through ADB
    device_list=CommandExecutor.execute("adb devices").split("\\r?\\n");
    System.out.println(device_list);
    if(device_list.length>1)
    {
        if(device_list[1].matches(".*\\d.*"))
        {
            device_id=device_list[1].split("\\s+");
            device_name=""+CommandExecutor.execute("adb -s "+device_id[0]+" shell getprop ro.product.manufacturer")+CommandExecutor.execute("adb -s "+device_id[0]+" shell getprop ro.product.model");
            device_name=device_name.replaceAll("\\s+"," ");
            System.out.println("\n"+device_name+" : "+device_id[0]);
            device=device_id[0];
            System.out.println("\n"+device);

        }
        else
        {
            System.out.println("Please attach a device");

        }
    }
    else
    {
        System.out.println("Please attach a device");

    }

CommandExecutor is a class which has the execute method in it. The code of the execute method is the same as posted above. This will check if any device is connected and if it connected, it will return it unique id number.

It is preferable to use id number while executing adb commands like :

adb -s "+device_id[0]+" shell getprop ro.product.manufacturer 

OR

adb -s <put-id-here> shell getprop ro.product.manufacturer

Note that '-s' is necesarry after adb.

Then using adb forward commnd you need to establish a tcp/ip socket. Here the desktop will be the client and mobile/device will be the server.

//Create socket connection
    try{
        socket = new Socket("localhost", 38300);
        System.out.println("Socket Created");
        out = new PrintWriter(socket.getOutputStream(), true);
        out.println("Hey Server!\n");

        new Thread(readFromServer).start();
        Thread closeSocketOnShutdown = new Thread() {
            public void run() {
                try {
                    socket.close();
                } 
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        Runtime.getRuntime().addShutdownHook(closeSocketOnShutdown);
    } 
    catch (UnknownHostException e) {
        System.out.println("Socket connection problem (Unknown host)"+e.getStackTrace());
    } catch (IOException e) {
        System.out.println("Could not initialize I/O on socket "+e.getStackTrace());
    }

Then you need read from the server i.e. the device :

private Runnable readFromServer = new Runnable() {

    @Override
    public void run() {
try {
            System.out.println("Reading From Server");
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while ((buffer=in.readLine())!=null) {
                System.out.println(buffer);
    }catch (IOException e) {
            try {
                in.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }

The 'buffer' will contain what device will send from its end of the app.

Now in your mobile application,you will need to open the same connection and siple write data to it out buffer

public class TcpConnection implements Runnable {

public static final int TIMEOUT=10;
private String connectionStatus=null;
private Handler mHandler;
private ServerSocket server=null; 
private Context context;
private Socket client=null;
private String line="";
BufferedReader socketIn;
PrintWriter socketOut;


public TcpConnection(Context c) {
    // TODO Auto-generated constructor stub
    context=c;
    mHandler=new Handler();
}

@Override
public void run() {
    // TODO Auto-generated method stub


    // initialize server socket
        try {
            server = new ServerSocket(38300);
            server.setSoTimeout(TIMEOUT*1000);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        //attempt to accept a connection
            try{
                client = server.accept();

                socketOut = new PrintWriter(client.getOutputStream(), true);
                socketOut.println("Hey Client!\n");
                socketOut.flush();

                syncContacts();

                Thread readThread = new Thread(readFromClient);
                readThread.setPriority(Thread.MAX_PRIORITY);
                readThread.start();
                Log.e(TAG, "Sent");
            }
            catch (SocketTimeoutException e) {
                // print out TIMEOUT
                connectionStatus="Connection has timed out! Please try again";
                mHandler.post(showConnectionStatus);
                try {
                    server.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            } 
            catch (IOException e) {
                Log.e(TAG, ""+e);
            } 

            if (client!=null) {
                try{
                    // print out success
                    connectionStatus="Connection succesful!";
                    Log.e(TAG, connectionStatus);
                    mHandler.post(showConnectionStatus);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }

}

private Runnable readFromClient = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            Log.e(TAG, "Reading from server");
            socketIn=new BufferedReader(new InputStreamReader(client.getInputStream()));
            while ((line = socketIn.readLine()) != null) {
                Log.d("ServerActivity", line);
                //Do something with line
            }
            socketIn.close();
            closeAll();
            Log.e(TAG, "OUT OF WHILE");
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
};

public void closeAll() {
    // TODO Auto-generated method stub
    try {
        Log.e(TAG, "Closing All");
        socketOut.close();
        client.close();
        server.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
} 

private Runnable showConnectionStatus = new Runnable() {
    public void run() {
        try
        {
            Toast.makeText(context, connectionStatus, Toast.LENGTH_SHORT).show();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
};
   }
 }


回答2:

Using Managed.adb in c#

AndroidDebugBridge bridge = AndroidDebugBridge.
CreateBridge(@"C:\Users\bla\AppData\Local\Android\Sdk\platform-tools\adb.exe", true); 

List<Device> devices = AdbHelper.Instance.
GetDevices(AndroidDebugBridge.SocketAddress); 

devices[0].CreateForward(38300, 38300); 

Then create a server socket on android to that port.

server = new ServerSocket(38300);
                server.setSoTimeout(TIMEOUT * 1000);
                socket = server.accept();

and client socket on C#

  TcpClient clientSocket = new System.Net.Sockets.TcpClient();
                clientSocket.Connect("127.0.0.1", 38300);