Android设备和PC端通过USB线通信

一、原理

通过 adb forward来实现,adb forward tcp:7777 tcp:8888。将本机7777端口收到的数据,转发到android设备的8888端口上。

二、实现步骤

1、在android设备上建立一个端口为8888的SocketServer,并打开server到监听状态,即serverSocket.accept()。
2、监听PC上的7777端口,即执行adb forward tcp:7777 tcp:8888。
3、在PC上开启端口为7777的socket客户端
4、socket建立成功后,通过输入输出流来进行通信

三、代码实现

1、android端

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author lixm
 *
 * 这里没有处理多客户端连接,可以开子线程,处理每一个socket
 */
public class MainActivity extends AppCompatActivity {

    ServerThread serverThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        serverThread = new ServerThread();
        serverThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        serverThread.setIsLoop(false);
    }

    /**
     * socket线程
     */
    class ServerThread extends Thread {
        private static final String TAG = "lixm";
        DataInputStream inputStream = null;
        DataOutputStream outputStream = null;

        boolean isLoop = true;
        private Socket socket = null;
        private boolean isStartSend = false;

        public void setIsLoop(boolean isLoop) {
            this.isLoop = isLoop;
        }

        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(8888);
                socket = serverSocket.accept(); // 这里开始阻塞,如果有人连上,则开始发送信息
                inputStream = new DataInputStream(socket.getInputStream());
                outputStream = new DataOutputStream(socket.getOutputStream());
                receiveData();
            } catch (Exception e) {
                e.printStackTrace();
                Log.d(TAG, "Exception ",e);
            } finally {
                if (serverSocket != null) {
                    try {
                        serverSocket.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        /**
         * 接收PC端过来的数据
         */
        private void receiveData(){
            new Thread(){                 // 接收数据的线程
                public void run(){
                    byte[] buffer = new byte[1024];
                    while (isLoop){
                        if(inputStream != null){
                            try {
                                Log.d("lixm","here will blocking");
                                int len = inputStream.read(buffer);
                                String receiveData = new String(buffer,0,len,"UTF-8");
                                Log.d("lixm","Server,receiveData = " + receiveData);
                                if(!TextUtils.isEmpty(receiveData) && receiveData.toLowerCase().equals("start")){
                                    isStartSend = true;
                                    sendData2Pc();
                                }else if(!TextUtils.isEmpty(receiveData) && receiveData.toLowerCase().equals("stop")){
                                    isStartSend = false;
                                    isLoop = false;
                                    socket.close();
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            Toast.makeText(MainActivity.this,"服务端关闭",Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                }
                            } catch (IOException e) {
                                Log.d("lixm","IOException : ",e);
                            }
                        }
                    }
                }
            }.start();
        }

        private void sendData2Pc(){  // 发送数据的线程
            new Thread(){
                public void run(){
                    int times = 1;
                    while(isStartSend){
                        String echo = "  send data: " + times + ", 这里是android端发出的信息。";
                        try {
                            outputStream.write(echo.getBytes("UTF-8"));
                            outputStream.flush();
                            Log.d(TAG, echo);
                            times ++;
                            Thread.sleep(1000);
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    }
}

2、pc端代码

/**

* @author 作者:lixm

* @createDate 创建时间:2019年7月12日

*/

public class DeviceManager {
    
    private static DeviceManager deviceManager = null;
    
    /**
     * 和android设备之间的连接
     */
    private Socket mSocket;
    
    /**
     * 输入流,接收来自android设备的数据
     */
    private DataInputStream inputStream;
    
    /**
     * 输出流,向android设备发出数据
     */
    private DataOutputStream outputStream;
    
    /**
     * 接收数据的线程
     */
    private ReceiveMsgThread receiveMsgThread = null;
    
    /**
     * 发送数据的线程
     */
    private SendMsgThread sendMsgThread = null;
    
    /**
     * 用于接收android端返回的数据
     */
    private IDataCallbackListener dataCallbackListener;
    
    private DeviceManager() {}
    
    public static DeviceManager getInstance() {
        if(deviceManager == null) {
            synchronized (DeviceManager.class) {
                if(deviceManager == null) {
                    deviceManager = new DeviceManager();
                }
            }
        }
        return deviceManager;
    }


    public IDataCallbackListener getDataCallbackListener() {
        return dataCallbackListener;
    }

    public void setDataCallbackListener(IDataCallbackListener dataCallbackListener) {
        this.dataCallbackListener = dataCallbackListener;
    }
    

    public void init() {
        stopSendThread();
        stopReceiveThread();
        releaseSocket();
    }

    /**
     * 初始化本地设备 
     * @param localPort    本地socket端口
     * @param androidPort  android设备端socketserver端口
     * @return true 成功 ,false 失败
     */
    public boolean initLoaclSocket(int localPort,int androidPort) {
        boolean isOk = false;
        try {
            Runtime.getRuntime().exec("adb forward tcp:" + localPort + " tcp:" + androidPort);
            isOk = true;
        } catch (IOException e) {
            e.printStackTrace();
            isOk = false;
        }
        if(isOk) {
            isOk = connectAndroidDevice(localPort);
        }
        return isOk;        
    }

    /**
     * 连接Android设备 , adb forward ,端口转发
     */
    private boolean connectAndroidDevice(int port) {
        boolean isOk = false;
        String ip;
        try {
            ip = InetAddress.getLocalHost().getHostAddress();
            System.out.println("ip = " + ip + ", port = " + port);
            ip = "127.0.0.1";
            mSocket = new Socket(ip,port);
            inputStream = new DataInputStream(mSocket.getInputStream());
            outputStream = new DataOutputStream(mSocket.getOutputStream());
            isOk = true;
        } catch (UnknownHostException e) {
            e.printStackTrace();
            isOk = false;
        }  catch (IOException e) {
            e.printStackTrace();
            isOk = false;
        }
        return isOk;
    }
    
    /**
     * 通过输入流接收android设备传来的数据
     */
    public void receiveData() {
        if(receiveMsgThread == null) {
            receiveMsgThread = new ReceiveMsgThread(inputStream);
            receiveMsgThread.setMsgReceive(true);
            receiveMsgThread.setDataCallbackListener(new IDataCallbackListener() {
                @Override
                public void onDataReceived(String data) {
                    if(dataCallbackListener != null) {
                        dataCallbackListener.onDataReceived(data);
                    }
                }
            });
        }
        receiveMsgThread.start();
    }

    /**
     * 发送数据
     * @param msg
     */
    public void sendData(String msg) {
        if(sendMsgThread == null) {
            sendMsgThread = new SendMsgThread(outputStream);
            sendMsgThread.start();
        }
        sendMsgThread.sendMsg(msg);
    }

    /**
     * 停止接收数据的线程
     */
    public void stopReceiveThread() {
        if(receiveMsgThread != null) {
            receiveMsgThread.release();
            receiveMsgThread = null;
        }
    }
    
    /**
     * 停止发送数据的线程
     */
    public void stopSendThread() {
        if(sendMsgThread != null) {
            sendMsgThread.release();
            sendMsgThread = null;
        }
        try {
            if(mSocket != null) {
                mSocket.close();
                mSocket = null;
            }           
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void releaseSocket() {
        try {
            if(inputStream != null) {
                inputStream.close();
                inputStream = null;
            }
            if(outputStream != null) {
                outputStream.close();
                outputStream = null;
            }
            if(mSocket != null) {
                mSocket.close();
                mSocket = null;
            }
            
        }catch(IOException e) {
            System.out.println("releaseSocket(),IOException :" + e.getMessage());
        }
        
    }
}
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class UI extends JFrame implements ActionListener
{

    JPanel jpannelConnect = null;
    JPanel jpannelReceiverTitle = null;
    JPanel jpannelStop = null;
    JPanel jpannelReceiverContent = null;  // 用于显示收到的内容

     //定义组件
    JButton jBtnConnect = null;  // 连接android设备
    JButton jBtnReceiveData = null;  // 接收数据
    
    JButton jBtnStopReceive = null;  // 停止接收数据

    JLabel  jLbConnectState;  // 连接状态的显示
    JLabel  jLbReceiveState;  // 数据接收状态的显示
    
    JTextArea jTxtReceiveContent = null;  //接收数据内容的显示 
    

    public static void main(String[] args) {
    }
    
    //构造函数
    public UI() 
    {
        
        jpannelConnect = new JPanel();
        jpannelReceiverTitle = new JPanel();
        jpannelReceiverContent = new JPanel();
        jpannelStop = new JPanel();

        //创建组件
        jBtnConnect = new JButton("建立连接");
        jBtnReceiveData = new JButton("接收数据");
        jBtnStopReceive = new JButton("停止接收数据");
        
        jLbConnectState = new JLabel("未连接");
        jLbReceiveState = new JLabel("未接收");        
        jTxtReceiveContent = new JTextArea(10,20);
        
        jTxtReceiveContent.setText("这里显示接收到的信息");
        
        jpannelConnect.add(jBtnConnect,LEFT_ALIGNMENT);
        jpannelConnect.add(jLbConnectState,LEFT_ALIGNMENT);
        jpannelStop.add(jBtnStopReceive);
        
        jpannelReceiverTitle.add(jBtnReceiveData);
        jpannelReceiverTitle.add(jLbReceiveState);
        jpannelReceiverContent.add(jTxtReceiveContent);
        
        this.add(jpannelConnect);
        this.add(jpannelReceiverTitle);
        this.add(jpannelReceiverContent);
        this.add(jpannelStop);
        
        initListener();
        
        //设置布局管理器
        this.setLayout(new GridLayout(3,3,50,50));
        this.setTitle("PC端和Android端的通信小工具");
        this.setSize(500,400);
        this.setLocation(300, 300);     
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

    }
    
    private IDataCallbackListener dataCallbackListener = new IDataCallbackListener() {
        
        @Override
        public void onDataReceived(String data) {
            if(jTxtReceiveContent != null && data != null && data.length() > 0) {
                jTxtReceiveContent.setText(data);
            }
        }
    };
    
    private void initListener() {
        jBtnConnect.addActionListener(this);        
        jBtnReceiveData.addActionListener(this);
        jBtnStopReceive.addActionListener(this);        
    }
    
    @Override
    public void actionPerformed(ActionEvent event) {
        String command = event.getActionCommand();
        if(command.equals("建立连接")) {
            DeviceManager.getInstance().init();
            boolean isOk = DeviceManager.getInstance().initLoaclSocket(7777, 8888);
            if(isOk) {
                jLbConnectState.setText("已连接");
            }
        }else if(command.equals("接收数据")) {
            DeviceManager.getInstance().setDataCallbackListener(dataCallbackListener);
            DeviceManager.getInstance().receiveData();
            DeviceManager.getInstance().sendData("start"); // 通知服务端开始发送数据
            jLbReceiveState.setText("数据接收中...");
        }else if(command.endsWith("停止接收数据")) {
            DeviceManager.getInstance().sendData("stop"); // 通知服务端停止发送数据
            DeviceManager.getInstance().stopReceiveThread();            
            jLbReceiveState.setText("数据接收停止");
        }       
    }
}

源码下载地址:
https://download.csdn.net/download/dami_lixm/11342681
————————————————

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容