Android设备和PC端通过USB线通信
16lz
2021-01-24
一、原理
通过 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() {@Overridepublic 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() {@Overridepublic 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);}@Overridepublic 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
更多相关文章
- Android(安卓)源码分析之旅3.1--消息机制源码分析
- android适配器SimpleCursorAdapter的使用以及最后一个参数的作用
- Android(安卓)HandlerThread用法
- 详解Android轻量型数据库SQLite
- android sql
- Android期末复习(3)-service
- 获取web服务器xml数据
- Android(安卓)Data Binding 技术
- 关于Android中传递数据的一些讨论