通过usb利用adb实现android手机和pc机通信

本文详细介绍了adbforward命令的原理,包括如何将PC端的8000端口数据转发到手机的9000端口,以及PC和Android端应用通过socket进行数据通信的过程。通过adb命令设置端口转发,手机端开启9000端口的server,PC端连接8000端口的server,实现数据双向传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、 adb forward 原理概述
adb forward 的功能是建立一个转发
如:adb forward tcp:8000 tcp:9000 的意思是,将PC端的 8000 端口收到的数据,转发给手机中的 9000 端口。
但是光执行这个命令还不能转发数据,还需要完成下面两个步骤才能传数据:

(a)在手机端,建立一个端口为9000的 server,并打开 server 到监听状态。
(b)在PC端,建立一个 socket client 端,连接到端口为8000的 server 上。
adb forward tcp:8000 tcp:9000 原理示意图:
在这里插入图片描述
PC端应用与手机端应用 通信建立过程:
(1)执行 adb forward tcp:8000 tcp:9000
(2)启动手机端应用,建立端口为9000的 server,并处于监听状态(LISTENING)
(3)启动PC端应用,连接端口为8000的 server(adb 创建的)之后,就可以传输数据了
PC端代码====


private static boolean mRunning = true;

    public static void main(String[] args) {
        if (!setupAdbForward()) {
            System.out.println("设置端口转发失败");
            return;
        } else {
            System.out.println("端口转发设置完成");
        }
        System.out.println("任意字符, 回车键发送");
        startClient();
    }

    private static boolean setupAdbForward() {
        try {
            // todo 将PC端8000端口的数据, 转发到Android端的9000端口上
            String device = "adb devices";
            Process process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", device});
            int ret = process.waitFor();
            System.out.println("cmy 111:" + device + ";" + ret);
            String forward = "adb forward tcp:8000 tcp:9000";
            process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", forward});
            process.waitFor();
            System.out.println("cmy 222:" + forward + ";" + ret);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    private static void startClient() {
        try {
            //设置pc端的端口为8000
            Socket socket = new Socket("127.0.0.1", 8000);
            // InThread 接收手机端传来的数据
            new Thread(new InThread(socket)).start();
            // OutThread 用于从PC端输入并传给手机端
            Scanner scanner = new Scanner(System.in);
            while (true) {
                String msg = scanner.next();
                sendToServer(socket, msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 接收手机端传来的数据
     */
    static class InThread implements Runnable {
        Socket socket;

        public InThread(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            while (mRunning) {
                if (socket.isClosed()) {
                    mRunning = false;
                    break;
                }
                try {
                    DataInputStream dis = new DataInputStream(socket.getInputStream());
                    byte[] buffer = new byte[256];
                    int len = dis.read(buffer);
                    if (len > 0) {
                        System.out.println("\n接收到:" + new String(buffer, 0, len, "UTF-8"));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 从PC端输入并传给手机端
     *
     * @param msg 信息
     * @throws IOException 异常
     */
    public static void sendToServer(Socket socket, String msg) throws IOException {
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        dos.writeUTF(msg);
        dos.flush();
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

PC端应用与手机端应用之间传输数据的过程:
(1)PC端应用将数据发送给端口为8000的 server(adb 创建的)
(2)adb 将数据转发给手机端 adbd 进程(通过USB传输)
(3)adbd 进程将数据发送给端口为9000的 server(手机端应用创建的)传递是双向的,
第(1)和第(3)步是通过socket实现的,所以通过 socket 的读和写就完成了PC端和手机端的数据传递。
=======andorid 端代码=

public class ServerThread extends Thread {
    private static final String SERVER_TAG = "server";
    private ServerSocket serverSocket;
    private Socket socket;
    boolean isLoop = true;

    public Socket getSocket() {
        return socket;
    }

    @Override
    public void run() {
        super.run();
        try {
            //设置Android端口为9000
            serverSocket = new ServerSocket(9000);
            while (isLoop) {
                try {
                    //从连接队列中取出一个连接,如果没有则等待
                    socket = serverSocket.accept();
                    Log.v(SERVER_TAG, "从连接队列中取出一个连接");
                    EventBus.getDefault().post(new MessageType("发现一个新的客户端加入:"));
                    while (true) {
                        /**
                         * isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()
                         * 这些方法无法判断服务端是否断开,只能判断本地的状态
                         */
                        // 发送心跳包,单线程中使用,判断socket是否断开
                        socket.sendUrgentData(0xFF);
                        DataInputStream inputStream = new DataInputStream(socket.getInputStream());
                        byte[] buffer = new byte[1024];
                        int bt;
                        String text = "";
                        int index = 0;
                        Log.v(SERVER_TAG, "inputStream.read 之前");
                        while ((bt = inputStream.read(buffer)) != -1) {
                            Log.v(SERVER_TAG, "bt:" + bt + ",," + (index++));
                            text += new String(buffer, 0, bt).trim();
                            Log.e(SERVER_TAG, "------------");
                            Log.e(SERVER_TAG, "text: " + text.trim());
                            /**
                             * 当接收到大数据,inputStream读取完后,由于inputStream通道是一直在的,
                             * inputStream.read(buffer)处在堵塞状态,所以并不会跳出当前循环,
                             * 导致无法判断数据是否传输完,所以PC端传输数据时需要在数据中
                             * 加入报尾,Android设备上接收到报尾,代表此次数据传输完毕,
                             * 也可以加上报头,来表示数据的开始
                             *
                             */
                            if (text.endsWith("-vvv")) {
                                EventBus.getDefault().post(new MessageType("接收:" + text));
                                text = text.substring(0, text.lastIndexOf("-vvv"));
                                Log.v(SERVER_TAG, "内容长度:" + text.length());
                                Log.v(SERVER_TAG, "读取结束,内容为:" + text);
                                Log.v(SERVER_TAG, "inputStream.read 之后");
                                break;
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    EventBus.getDefault().post(new MessageType("接收:异常"));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class SendThread extends Thread {
    private String data;
    private Socket socket;

    public SendThread(String data, Socket socket) {
        this.data = data + "-vvv";
        this.socket = socket;
    }

    @Override
    public void run() {
        super.run();
        sendDatas();
    }

    private void sendDatas() {
        try {
            DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
            outputStream.write(data.getBytes("UTF-8"));
            outputStream.flush();
            LogUtils.e("发送:" + data);
            EventBus.getDefault().post(new MessageType("发送:" + data));
        } catch (IOException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new MessageType("发送:异常"));
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值