預研目標
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.net.Socket;
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 異常
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());
//給手機端發送數據
dos.writeUTF("我是來自pc端的數據");
//拿到socket的輸入流,也就是手機端發來的數據流
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
//讀取來自手機端的數據
String msg = inputStream.readUTF();
System.out.println("收到來自手機端發來的數據: " + msg);
//最後關閉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即可實現雙向通信。