1、 adb forward 原理概述
adb forward 的功能是建立一個轉發(fā)
如:adb forward tcp:8000 tcp:9000 的意思是,將PC端的 8000 端口收到的數(shù)據(jù),轉發(fā)給手機中的 9000 端口。
但是光執(zhí)行這個命令還不能轉發(fā)數(shù)據(jù),還需要完成下面兩個步驟才能傳數(shù)據(jù):
(a)在手機端,建立一個端口為9000的 server,并打開 server 到監(jiān)聽狀態(tài)。
(b)在PC端,建立一個 socket client 端,連接到端口為8000的 server 上。
adb forward tcp:8000 tcp:9000 原理示意圖:
PC端應用與手機端應用 通信建立過程:
(1)執(zhí)行 adb forward tcp:8000 tcp:9000
(2)啟動手機端應用,建立端口為9000的 server,并處于監(jiān)聽狀態(tài)(LISTENING)
(3)啟動PC端應用,連接端口為8000的 server(adb 創(chuàng)建的)之后,就可以傳輸數(shù)據(jù)了
PC端代碼====文章來源:http://www.zghlxwxcb.cn/news/detail-816181.html
private static boolean mRunning = true;
public static void main(String[] args) {
if (!setupAdbForward()) {
System.out.println("設置端口轉發(fā)失敗");
return;
} else {
System.out.println("端口轉發(fā)設置完成");
}
System.out.println("任意字符, 回車鍵發(fā)送");
startClient();
}
private static boolean setupAdbForward() {
try {
// todo 將PC端8000端口的數(shù)據(jù), 轉發(fā)到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 接收手機端傳來的數(shù)據(jù)
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();
}
}
/**
* 接收手機端傳來的數(shù)據(jù)
*/
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端應用與手機端應用之間傳輸數(shù)據(jù)的過程:
(1)PC端應用將數(shù)據(jù)發(fā)送給端口為8000的 server(adb 創(chuàng)建的)
(2)adb 將數(shù)據(jù)轉發(fā)給手機端 adbd 進程(通過USB傳輸)
(3)adbd 進程將數(shù)據(jù)發(fā)送給端口為9000的 server(手機端應用創(chuàng)建的)傳遞是雙向的,
第(1)和第(3)步是通過socket實現(xiàn)的,所以通過 socket 的讀和寫就完成了PC端和手機端的數(shù)據(jù)傳遞。
=======andorid 端代碼=文章來源地址http://www.zghlxwxcb.cn/news/detail-816181.html
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("發(fā)現(xiàn)一個新的客戶端加入:"));
while (true) {
/**
* isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()
* 這些方法無法判斷服務端是否斷開,只能判斷本地的狀態(tài)
*/
// 發(fā)送心跳包,單線程中使用,判斷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());
/**
* 當接收到大數(shù)據(jù),inputStream讀取完后,由于inputStream通道是一直在的,
* inputStream.read(buffer)處在堵塞狀態(tài),所以并不會跳出當前循環(huán),
* 導致無法判斷數(shù)據(jù)是否傳輸完,所以PC端傳輸數(shù)據(jù)時需要在數(shù)據(jù)中
* 加入報尾,Android設備上接收到報尾,代表此次數(shù)據(jù)傳輸完畢,
* 也可以加上報頭,來表示數(shù)據(jù)的開始
*
*/
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("發(fā)送:" + data);
EventBus.getDefault().post(new MessageType("發(fā)送:" + data));
} catch (IOException e) {
e.printStackTrace();
EventBus.getDefault().post(new MessageType("發(fā)送:異常"));
}
}
}
到了這里,關于通過usb利用adb實現(xiàn)android手機和pc機通信的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!