Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 高級開發 >> Android開發進階之NIO非阻塞包(六)

Android開發進階之NIO非阻塞包(六)

編輯:高級開發

有關android NIO的相關內容,本次Android123整理並歸類如下,為了讓大家感覺NIO和android平台聯系的緊密,這裡我們結合ADT插件的重要開發工具DDMS中的源碼進行分析。在android git中的sdk.git文件中,可以找到ddmlib這個文件夾。有關PC和手機的互通內核在這裡使用了Java來完全實現。這裡android開發網一起幫助大家了解下PC同步軟件的開發原理同時學習下Java中的New I/O技術

比較重要的代碼段我們貼出,逐一分析,其他的網友可以直接預讀源碼:

AdbHelper.Java文件中

public static SocketChannel open(InetSocketAddress adbSockAddr,
Device device, int devicePort) //這是一個重載版本,主要是關聯Device實例。
throws IOException, TimeoutException, AdbCommandRejectedException {

SocketChannel adbChan = SocketChannel.open(adbSockAddr); //構造SocketChannel對象,使用常規的open方法創建
try {
adbChan.socket().setTcpNoDelay(true); //設置TCP非延遲
adbChan.configureBlocking(false); //非阻塞

setDevice(adbChan, device); //本句和NIO沒有多大關系,這句是指定具體的設備,比如模擬器,或android手機的廠家代號,比如宏達電的以HTXXXXX這樣的方式

byte[] req = createAdbForwardRequest(null, devicePort); //設置端口轉發,這句很關鍵,否則PC和手機通過USB是無法互通的。
write(adbChan, req); //發送數據

AdbResponse resp = readAdbResponse(adbChan, false); //讀取收到的內容
if (resp.okay == false) {
throw new AdbCommandRejectedException(resp.message);
}

adbChan.configureBlocking(true);
} catch (TimeoutException e) { //一般要處理超時異常
adbChan.close(); //釋放channel句柄
throw e;
} catch (IOException e) { //處理常規的IO異常
adbChan.close();
throw e;
}

return adbChan;
}

有關讀取ADB返回的報文方法

static AdbResponse readAdbResponse(SocketChannel chan, boolean readDiagString)
throws TimeoutException, IOException {

AdbResponse resp = new AdbResponse();

byte[] reply = new byte[4]; //創建4字節數組,主要檢測成功與否,adb的協議是成功返回 okay,失敗fail,等等。
read(chan, reply); //讀取具體的返回

if (isOkay(reply)) { //判斷是否成功
resp.okay = true;
} else {
readDiagString = true; // look for a reason after the FAIL
resp.okay = false;
}

// not a loop -- use "while" so we can use "break"
try {
while (readDiagString) {
// length string is in next 4 bytes
byte[] lenBuf = new byte[4];
read(chan, lenBuf); //讀取一個字節數組,最終為了轉為一個整形

String lenStr = replyToString(lenBuf); //字節數組轉為String

int len;
try {
len = Integer.parseInt(lenStr, 16); //String轉為整形,這裡android123提示,這種寫法可能比較愚蠢,但是下面為Log輸出提供了一點點的便利。
} catch (NumberFormatException nfe) {
Log.w("ddms", "Expected digits, got '" + lenStr + "': "
+ lenBuf[0] + " " + lenBuf[1] + " " + lenBuf[2] + " "
+ lenBuf[3]);
Log.w("ddms", "reply was " + replyToString(reply));
break;
}

byte[] msg = new byte[len];
read(chan, msg);

resp.message = replyToString(msg);
Log.v("ddms", "Got reply '" + replyToString(reply) + "', diag='"
+ resp.message + "'");

break;
}
} catch (Exception e) {
// ignore those, since it's just reading the diagnose string, the response will
// contain okay==false anyway.
}

return resp;
}

有關PC上對android手機屏幕截圖的方法之一:

static RawImage getFrameBuffer(InetSocketAddress adbSockAddr, Device device)
throws TimeoutException, AdbCommandRejectedException, IOException {

RawImage imageParams = new RawImage();
byte[] request = formAdbRequest("framebuffer:"); // 讀取手機端adbd服務器的framebuffer調用返回的數組

byte[] nudge = {
0
};
byte[] reply;

SocketChannel adbChan = null;
try {
adbChan = SocketChannel.open(adbSockAddr);
adbChan.configureBlocking(false); //非阻塞

setDevice(adbChan, device); //設置我們關系的設備

write(adbChan, request); //發送framebuffer這個請求了

AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
if (resp.okay == false) { //判斷返回是否ok。
throw new AdbCommandRejectedException(resp.message);
}

reply = new byte[4];
read(adbChan, reply); //首先返回的是一個協議,目前分為兩個版本,主要是兼容模式和標准的模式,兼容模式比較少見,在2.0以後幾乎看不到了。部分早期的1.6或更老的T-Mobile G1會使用兼容模式,模式不同,輸出的截圖中的顏色編碼方式略有不同。

ByteBuffer buf = ByteBuffer.wrap(reply);
buf.order(ByteOrder.LITTLE_ENDIAN); //小頭字節順序

int version = buf.getInt(); //ByteBuffer直接轉int的方法,比較方便不用自己從字節數組中構造,按位計算

int headerSize = RawImage.getHeaderSize(version); //根據返回的adb截圖協議版本判斷將收到的字節大小

reply = new byte[headerSize * 4]; //分配空間,具體大小需要看協議版本
read(adbChan, reply);

buf = ByteBuffer.wrap(reply); //從reply數組實例化ByteBuffer
buf.order(ByteOrder.LITTLE_ENDIAN); //注意字節序列,畢竟遠端的adbd是工作在Linux系統的手機上。

if (imageParams.readHeader(version, buf) == false) { //判斷是否有效,兼容這種截圖協議。
Log.e("Screenshot", "Unsupported protocol: " + version);
return null;
}

Log.d("ddms", "image params: bpp=" + imageParams.bpp + ", size="
+ imageParams.size + ", width=" + imageParams.width
+ ", height=" + imageParams.height); //打印下截圖的基本信息,比如bpp代表色深,size是需要分配dib圖像的字節數組。比較原始,

write(adbChan, nudge); //發送一個字節,代表准備接收字節數組了

reply = new byte[imageParams.size]; //分配和圖像大小一樣的字節數組
read(adbChan, reply); //接收圖像字節數組,這裡Android開發網提示大家對於android 1.x可能為RGB565,分配大小為 wxhx2xsize ,而2.x以後基本上為32位的RGB8888,分配大小為wxhx4xsize

imageParams.data = reply;
} finally {
if (adbChan != null) {
adbChan.close();
}
}

return imageParams;
}

有關Android平台PC通過USB的ADB方式和手機同步原理和NIO相關技術,android123明天繼續講解。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved