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