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

news2024/11/22 18:46:06

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("发送:异常"));
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【主色提取】HSV 颜色空间与 RGB 颜色空间互相转化的公式和代码

系列文章目录 第二章 主色提取之颜色空间转化 目录 系列文章目录 文章目录 前言 一、HSV 和 RGB 颜色空间 二、颜色转化 1. RGB to HSV 2. HSV to RGB 三、 完整代码 前言 HSV 颜色空间和 RGB 颜色空间的转化。 一、HSV 和 RGB 颜色空间 RGB颜色使用的最多&#xff0…

C语言详解【通讯录的实现】

前言: 在之前的学习中我们已经了解了结构体的一些知识,有了之前的知识的储备,在这里我们就可以尝试通讯录的实现。 目录问题描述基本流程前期的准备工作实现过程第一阶段第二阶段第三阶段1.增加联系人2.删除联系人3.打印通讯录4.查找指定联系…

高等数学(第七版)同济大学 习题11-7 个人解答

高等数学(第七版)同济大学 习题11-7 函数作图软件:Mathematica 1.试对曲面Σ:zx2y2,x2y2≤1,Py2,Qx,Rz2验证斯托克斯公式.\begin{aligned}&1. \ 试对曲面\Sigma:zx^…

yolov5+车道线检测

目标检测与车道线检测在自动驾驶以及车辆定位中起着重要的辅助作用,是环境感知中不可缺少的一个部分。基于深度学习的车道线检测方法近年来也在不断的提升,比如论文:Ultra Fast Deep Lane Detection with HybridAnchor Driven Ordinal Classi…

Allegro如何Wavie DRC操作指导

Allegro如何Wavie DRC操作指导 在做PCB设计的时候,会因为规则设置的原因,导致出现很多DRC,不方便检查,Allegro支持直接Waive掉正常DRC,方便检查,如下图 芯片中心需要打过孔方便散热,但是这些过孔的DRC是不需要显示的 具体操作如下 选择Display选择 Waive DRCs

数据结构与算法3—栈

1. 栈的定义 栈,也叫堆栈,是最常用也是最重要的数据结构之一。栈(Stack)是限定仅在表的一端进行插入或删除操作的线性表,通常称插入、删除的这一端为栈顶(Top),另一端为栈底(Bottom)。当表中没有元素时称为空栈。栈操作的特点&am…

【服务器数据恢复】StorNext文件系统数据恢复案例

服务器数据恢复环境: 昆腾系列存储,9个磁盘柜,每个磁盘柜配置24块硬盘。其中8个磁盘柜用于存储数据,1个磁盘柜用于存储元数据。上层使用的是StorNext文件系统。 存储元数据的磁盘柜中24块磁盘的分配情况:8组RAID1阵列1…

1361. 验证二叉树

目录题目思路代码题目 二叉树上有 n 个节点,按从 0 到 n - 1 编号,其中节点 i 的两个子节点分别是 leftChild[i] 和 rightChild[i]。 只有 所有 节点能够形成且 只 形成 一颗 有效的二叉树时,返回 true;否则返回 false。 如果节点…

开发小程序遇到的问题

1、小程序授权定位时报错 原因: 需要授权 scope.userLocation、scope.userLocationBackground 时必须配置地理位置用途说明。 解决: 在app.json中,根据开发文档的提示,将下面的代码添加在与pages同级下 "permission": {…

16年经验的通信行业测试人,后悔入错行了吗?

屏幕前的读者对于一个行业的兴衰有什么看法呢?非常很现实的说,我们所处的行业直接关系着每个人的收入,处于行业的不同生命周期内,我们拿到的钱也会不一样。下面用本人所处的行业举个例子。工作经历初入通信行业从我进入通信行业的…

什么是SPI?SPI的优点有哪些?

1、什么是SPI? SPI是串行外设接口(Serial Peripheral Interface)的缩写,是Motorola公司推出的一种同步串行接口技术,是一种高速、全双工、同步的通信总线。 2、SPI优点 支持全双工通信通信简单数据传输速率块 3、缺…

案例分析中可能的考点1:招投标程序

招投标程序: (1)投标方不满足资质要求; (2)投标过程不满足时间要求; (3)招标公告内容或过程不满足要求; (4)评标人员不满足组成要求&a…

【数据结构与算法】二叉树的非递归前中后序遍历

🌠作者:阿亮joy. 🎆专栏:《数据结构与算法要啸着学》 🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉…

WebSphere8 批量安装和制作介质服务器

WAS 8.5 介质准备 1、安装install manager 2、安装IBM Packaging Utility unzip pu.offering.disk.linux_1.5.3000.20120531_2025.zip cd disk_linux/InstallerImage_linux ./consoleinst.sh 跟着向导安装。 3、安装PU mkdir pu cd pu unzip ../pu_1.5.3.zip ./imcl i…

如何使用集成在 SharePoint 中的开源 ONLYOFFICE 文档替代微软 Office

ONLYOFFICE 文档是一款开源的办公套件,在 GNU AGPL v3.0 下分发。它包括基于网络的查看器和协作编辑器,可用于处理文本文档、电子表格和演示文稿,与 OOXML 格式高度兼容。 ONLYOFFICE 文档可以与多种云服务集成,如 Nextcloud、ow…

仅CPU服务器pytorch ,torch_geometric安装配置

写在开头,做了整整三年的多组学数据分析,各种模式动物、组织、细胞系的各种组学数据,该怎么串联成我的论文?就是我要开启深度学习小白模式了。 万种流程先从环境配置开始,先说说环境,其实当家的有多GPU超大…

儿童护眼灯哪个好?四款儿童护眼台灯测评

儿童护眼灯在孩子的学习过程中起到了很重要的作用,53.7%的青少年们都有近视的现象,而好的台灯不仅照明非常柔和,而且对眼睛没有刺激和伤害,护眼灯相比传统电灯,一是古县更加明亮且可以调节,二是有护眼技术的…

HANA 的 calculation view出现模糊关联 ambiguous join

一旦我们用了join,那就会有个Analytic Engine分析引擎来确保不是唯一连接的时候,关键值不会被重复。 啥是模糊关联? 一般来讲关联基数是1:n, 或者n:1,或者 m:n都是。 以上两个关联,结果集如下: 这时候&a…

php学习笔记-php会话控制,cookie,session的使用,cookie自动登录和session 图书上传信息添加和修改例子-day07

php学习笔记-php会话控制及web常用的预定义变量-day071、$_REQUEST2、$_SERVER3、$_COOKIE3.1 cookie的内容3.2 cookie的分类3.3 php中cookie的使用3.4 cookie自动登录小demo4、$SESSION4.1 session的工作原理4.2 session的使用4.2.1 修改php.ini中的session配置4.2.2 开启sess…

Android 深入系统完全讲解(13)

3 编译过程讲解 1 系统的编译过程 Android 的编译使用的 Makefile,推荐大家使用《GNU make 中文手册》,这本书有电子版,非常方便,主要是要理解清楚 Makefile 的规则,编译策略,可以通过写简单的编译机制&am…