[Android] PhoneGap 소스 코드 분석 - CallbackServer 비동기 리 셋

7663 단어
Phone Gap 의 js 리 셋 은 몇 가지 실현 방식 이 있다.그 중 하 나 는 ajax 입 니 다.
    먼저 js 엔 드 관련 코드 를 살 펴 보 겠 습 니 다.
// file: lib/android/plugin/android/callback.js
define("cordova/plugin/android/callback", function(require, exports, module) {

var port = null,
    token = null,
    xmlhttp;

function startXhr() {
    // cordova/exec depends on this module, so we can't require cordova/exec on the module level.
    var exec = require('cordova/exec'),
    xmlhttp = new XMLHttpRequest();

    // Callback function when XMLHttpRequest is ready
    xmlhttp.onreadystatechange=function(){
        if (!xmlhttp) {
            return;
        }
        if (xmlhttp.readyState === 4){
            // If callback has JavaScript statement to execute
            if (xmlhttp.status === 200) {

                // Need to url decode the response
                var msg = decodeURIComponent(xmlhttp.responseText);
                setTimeout(startXhr, 1);
                exec.processMessages(msg);
            }

            // If callback ping (used to keep XHR request from timing out)
            else if (xmlhttp.status === 404) {
                setTimeout(startXhr, 10);
            }

            // 0 == Page is unloading.
            // 400 == Bad request.
            // 403 == invalid token.
            // 503 == server stopped.
            else {
                console.log("JSCallback Error: Request failed with status " + xmlhttp.status);
                exec.setNativeToJsBridgeMode(exec.nativeToJsModes.POLLING);
            }
        }
    };

    if (port === null) {
        port = prompt("getPort", "gap_callbackServer:");
    }
    if (token === null) {
        token = prompt("getToken", "gap_callbackServer:");
    }
    xmlhttp.open("GET", "http://127.0.0.1:"+port+"/"+token , true);
    xmlhttp.send();
}

module.exports = {
    start: function() {
        startXhr();
    },

    stop: function() {
        if (xmlhttp) {
            var tmp = xmlhttp;
            xmlhttp = null;
            tmp.abort();
        }
    },

    isAvailable: function() {
        return ("true" != prompt("usePolling", "gap_callbackServer:"));
    }
};


});

    주요 처 리 는 startXhr 함수 입 니 다.자바 의 server 쪽 에 ajax 요청 을 했 습 니 다. onready statechange 라 는 반전 함수 에서 server 쪽 이 결 과 를 되 돌려 주 기 를 기다 리 고 있 습 니 다.server 엔 드 가 돌아 온 결과 가 정확 하 다 면 setTimeout (startXhr, 1) 함 수 를 통 해 1 호 초 후에 server 엔 드 에 ajax 요청 을 다시 합 니 다.server 에서 돌아 온 결과 상태 가 404 이면 10 호 초 간격 으로 server 쪽 에 ajax 요청 을 다시 합 니 다.
    다음은 server 엔 드 가 어떻게 처리 되 는 지 살 펴 보 겠 습 니 다.server 엔 드 의 처리 코드 는 CallbackServer. 자바 의 run () 방법 입 니 다.
    서버 쪽 의 원본 코드 를 먼저 봅 니 다:
    이것 은 server Socket 을 통 해 http 의 server 단 을 모 의 합 니 다.그 중에서 jsMessage Queue 는 자바 에서 보 낸 js 메시지 입 니 다. server Socket 은 클 라 이언 트 (js 엔 드) 의 요청 을 받 은 후에 jsMessage Queue 의 js 코드 를 클 라 이언 트 (js 엔 드) 에 보 냅 니 다.
    /**
     * Start running the server.  
     * This is called automatically when the server thread is started.
     */
    public void run() {

        // Start server
        try {
            this.active = true;
            String request;
            waitSocket = new ServerSocket(0);
            this.port = waitSocket.getLocalPort();
            //Log.d(LOG_TAG, "CallbackServer -- using port " +this.port);
            this.token = java.util.UUID.randomUUID().toString();
            //Log.d(LOG_TAG, "CallbackServer -- using token "+this.token);

            while (this.active) {
                //Log.d(LOG_TAG, "CallbackServer: Waiting for data on socket");
                Socket connection = waitSocket.accept();
                BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()), 40);
                DataOutputStream output = new DataOutputStream(connection.getOutputStream());
                request = xhrReader.readLine();
                String response = "";
                //Log.d(LOG_TAG, "CallbackServerRequest="+request);
                if (this.active && (request != null)) {
                    if (request.contains("GET")) {

                        // Get requested file
                        String[] requestParts = request.split(" ");

                        // Must have security token
                        if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
                            //Log.d(LOG_TAG, "CallbackServer -- Processing GET request");
                        	String payload = null;

                            // Wait until there is some data to send, or send empty data every 10 sec 
                            // to prevent XHR timeout on the client 
                            while (this.active) {
                            	if (jsMessageQueue != null) {
                            		payload = jsMessageQueue.popAndEncode();
                            	    if (payload != null) {
                            	    	break;
                            	    }
                            	}
                            	synchronized (this) {
                                    try {
                                        this.wait(10000); // prevent timeout from happening
                                        //Log.d(LOG_TAG, "CallbackServer>>> break <<<");
                                        break;
                                    } catch (Exception e) {
                                    }
                                }
                            }

                            // If server is still running
                            if (this.active) {

                                // If no data, then send 404 back to client before it times out
                                if (payload == null) {
                                    //Log.d(LOG_TAG, "CallbackServer -- sending data 0");
                                    response = "HTTP/1.1 404 NO DATA\r
\r
"; // need to send content otherwise some Android devices fail, so send space } else { //Log.d(LOG_TAG, "CallbackServer -- sending item"); response = "HTTP/1.1 200 OK\r
\r
"; response += encode(payload, "UTF-8"); } } else { response = "HTTP/1.1 503 Service Unavailable\r
\r
"; } } else { response = "HTTP/1.1 403 Forbidden\r
\r
"; } } else { response = "HTTP/1.1 400 Bad Request\r
\r
"; } //Log.d(LOG_TAG, "CallbackServer: response="+response); //Log.d(LOG_TAG, "CallbackServer: closing output"); output.writeBytes(response); output.flush(); } output.close(); xhrReader.close(); } } catch (IOException e) { e.printStackTrace(); } this.active = false; //Log.d(LOG_TAG, "CallbackServer.startServer() - EXIT"); }

좋은 웹페이지 즐겨찾기