如何通过USB从Android向Windows发送消息

13

我对Android完全是个新手,只能写出基本的(1或2行)由按钮触发的Activity,但我想创建一个非常简单的应用程序,当我点击应用程序图标时,它会向我的Windows 8 PC上的监听服务器发送一条消息并忘记。手机连接为简单的媒体设备,通过USB电缆而没有Kies。

我可以让一个消息框弹出并说消息已经发送。我需要知道如何使用什么样的通信通道,例如COM端口等,并了解如何从Android发送数据到该端口。在Windows方面,一旦我确定如何通信,我就可以自己处理。


Profk没有任何关于COM端口命令或任何代码的想法,可以让Android从Windows发送和接收数据。 - Chetan Joshi
2个回答

18

首先从桌面端开始,您可以使用ADB(Android调试桥)通过端口建立设备与桌面之间的tcp/ip套接字连接。命令如下:

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

要在Java程序中运行此命令,您需要创建一个进程构建器,在其中将此命令作为子shell执行。

对于Windows系统,您可能需要使用:

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();
        }

执行adb命令所需的函数:

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();
        }
上述方法将把上述命令作为字符串在子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是一个类,其中包含execute方法。执行方法的代码与上面发布的相同。此将检查是否连接了任何设备,如果连接,则返回其唯一ID号码。

在执行adb命令时最好使用ID号码,例如:

adb -s "+device_id[0]+" shell getprop ro.product.manufacturer 
OR
adb -s <put-id-here> shell getprop ro.product.manufacturer

请注意,在adb后面需要加上'-s'。

然后,使用adb forward命令,您需要建立一个TCP/IP套接字。在这里,桌面将是客户端,移动设备将是服务器。

//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());
    }

那么你需要从服务器即设备中读取:

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();
        }
    }

'缓冲区'将包含设备从其应用程序端发送的内容。

现在,在您的移动应用程序中,您需要打开相同的连接并简单地将数据写入其输出缓冲区。

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();
        }
    }
};
   }
 }

哇!这些都是因为 USB 所必需的吗?还是我可以直接打开 WLAN 套接字连接呢?生产应用程序肯定不会使用调试桥来进行网络连接吧?但是感谢您提供的所有详细信息。 - ProfK
我不知道 WLAN sockets(无线局域网套接字)的情况...这是我为我的应用程序所做的方式。 - Ab5
我假设通过Wifi局域网的套接字连接与有线局域网上的相同。 - ProfK
是的,我已经检查过了,所有这些都是必要的,因为通信是通过USB进行的,为此我们使用ADB使用Wifi LAN套接字甚至蓝牙连接将大大减少代码。 - Ab5
@NaveedAli,adb命令“adb forward tcp:<端口号> tcp:<端口号>”是该命令的值。 - Ab5
1
安卓应用和Windows Java应用的代码在哪里? - user924

3

使用c#中的Managed.adb

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); 

然后在Android上创建一个服务器套接字到该端口。
server = new ServerSocket(38300);
                server.setSoTimeout(TIMEOUT * 1000);
                socket = server.accept();

以及C#上的客户端套接字

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

如何获取AndroidDebugBridge - Aaron Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接