预研目标
Android设备和PC设备在有线USB连接情况下能否双向通信,如何实现?
测试代码
PC端代码实现
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Test {
public static void main(String[] args) {
try {
//adb 的路径
String adbHome = "/Users/yinhaide/Library/Android/sdk/platform-tools/adb ";
//adb查看版本号
String versionCmd = adbHome + "--version";
//pc和手机的端口转发命令,可参考:https://blog.csdn.net/u013553529/article/details/80036227
//不执行转发的话会出现:Connection refused 异常,pc或者手机端任意一端执行都可以
String forwardCmd = adbHome + "forward tcp:8004 tcp:8004";
//pc和手机的端口转发,两边端口号可一样也可以不一样,自行定义,不执行的话两边无法通信
exec(forwardCmd);
//测试读取adb版本号
System.out.println("versionCmd: " + exec(versionCmd));
//连接adb服务器,本地ip,也就是通过有线方式,需要手机端先开启服务器监听来自pc的socket连接
Socket socket = new Socket("127.0.0.1", 8004);
//socket的输出流,用来给手机端写数据
//DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
OutputStream writer = socket.getOutputStream();
//writer.write("WXU138|0|1.0.0|{\"action\":\"pay_success\",\"cardid\":\"1245444\",\"userid\":\"haideyin\",\"total\":1,\"order_time\":126548951}|01a09092c13a58dd288f0e9bd7b641d7\r\n".getBytes());
writer.write("WXU69|12|1.0.0|{\"action\":\"pay\",\"total\":1}|cc3d4f642efb68525ea4a7d21ff5ad7e\r\n".getBytes());
//writer.write("WXU65|18|1.0.0|{\"action\":\"heartbeat\"}|153e2de52b54c5138f75112217138d47\r\n".getBytes());
//writer.write("WXU62|19|1.0.0|{\"action\":\"cancel\"}|767f0c839210383786b371bd10094ea3\r\n".getBytes());
//writer.write("WXC83|1|{\"action\":\"cancel\",\"errmsg\":\"哈哈哈哈\",\"errcode\":0}|2dc2f47c203b1a62d02031de9f5211ac\r\n".getBytes());
writer.flush();
//给手机端发送数据
//dos.writeUTF("我是来自pc端的数据");
//拿到socket的输入流,也就是手机端发来的数据流
InputStream inputStream = socket.getInputStream();
while (true) {
final int MLEN = 1024;
byte[] buff = new byte[MLEN];
int size = inputStream.read(buff);
//读取来自手机端的数据
if (size >= 0) { // 包超缓冲
String data = new String(buff, StandardCharsets.UTF_8);
System.out.println("收到来自手机端的数据:"+ data);
}
}
//dos.writeUTF("我是来自pc端的数据222");
//最后关闭socket
//socket.close();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
/**
* 执行adb指令
* @param cmd adb指令
* @return 返回执行结果的字符串
*/
public static String exec(String cmd){
Process process;
try {
process=Runtime.getRuntime().exec(cmd);
return InputStream2String(process.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* adb指令的InputStream转成字符串输出
* @param inputStream adb指令inputStream
* @return 返回执行结果的字符串
*/
public static String InputStream2String(InputStream inputStream){
String result="";
BufferedReader br=new BufferedReader(new InputStreamReader(inputStream));
try {
String temp="";
while ((temp=br.readLine())!=null){
result+=temp+"\n";
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
- Android端代码实现
package com.example.myapplication;
import android.util.Log;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
class AndroidServer extends Thread {
@Override
public void run() {
//如果出现端口占用 请参考解决方案:https://www.cnblogs.com/mantti/p/5262902.html
ServerSocket serverSocket = null;
try {
//建立socket服务器,监听手机8004端口,这的端口与pc端的端口不属于同个端口,需要adb forward指令去关联转换才能通信
serverSocket = new ServerSocket(8004);
while (true) {
//接受客户端连接
Socket socket = serverSocket.accept();
//读取连接的输入流,也就是pc端发来的数据
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
//拿到pc端发来的数据
String msg = inputStream.readUTF();
Log.d("AndroidServer", "收到来自pc端的数据: " + msg);
//拿到socket的输出流,给pc端写数据
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
//给pc端写数据
outputStream.writeUTF("我是来自手机端的数据");
//关闭单次连接的socket
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
测试步骤
测试前提是pc端已经安装好adb驱动,正常情况下要跟手机设备通信都是需要adb驱动的
- 1、Android端启动socket服务,监听8004端口
new AndroidServer().start();
- 2、pc端执行adb端口转发指令
adb forward tcp:8004 tcp:8004
- 3、pc端发起socket连接本地服务器的8004端口
Socket socket = new Socket("127.0.0.1", 8004);
- 4、双方进行数据传输
//读取数据
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
String msg = inputStream.readUTF();
//写入数据
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("我是来自手机端的数据");
测试结果
- pc代码执行结果
versionCmd: Android Debug Bridge version 1.0.41
Version 30.0.2-6538114
Installed as /Users/yinhaide/Library/Android/sdk/platform-tools/adb
收到来自手机端发来的数据: 我是来自手机端的数据
- 手机代码执行结果
2020-06-20 14:14:41.755 6923-6973/com.example.myapplication D/AndroidServer: 收到来自pc端的数据: 我是来自pc端的数据
测试结论
方案可行,在有线连接下借助adb驱动和socket即可实现双向通信。