Update v1.2.2版本的 MD5 值为:87ab33f0c8bd4c1dd345062aa2794e73

以下内容为反编译后的 Client.java 源代码,内容仅作参考


package cn.bmob.v3.realtime;

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Base64;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.helper.BmobNative;
import cn.bmob.v3.helper.ErrorCode;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashSet;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Client {
    public static final String ACTION_DELETE_ROW = "deleteRow";
    public static final String ACTION_DELETE_TABLE = "deleteTable";
    public static final String ACTION_UPDATE_ROW = "updateRow";
    public static final String ACTION_UPDATE_TABLE = "updateTable";
    public static final String DEFAULT_REAL_TIME_DATA_HOST = "http://io.bmob.cn:3010/socket.io/1/";
    public static final String DEFAULT_REAL_TIME_DATA_PATH_WEBSOCKET = "websocket/";
    public static final String PROTOCOL_WEBSOCKET = "websocket";
    public static final String TAG = "Client";
    private ClientListener mClientListener;
    private WebSocket mWebSocket;
    int ackCount = 0;
    private thing mListenHandler = new thing(this, (byte) 0);
    private OkHttpClient mOkHttpClient = new OkHttpClient();

    public interface ClientListener {
        void onConnectCompleted(Client client, Exception exc);

        void onDataChange(Client client, JSONObject jSONObject);
    }

    public interface of {
        void Code();

        void Code(Exception exc);

        void Code(String str, String str2);

        void Code(WebSocket webSocket);

        void Code(JSONObject jSONObject);

        void V();
    }

    public void connect(ClientListener clientListener) {
        this.mClientListener = clientListener;
        new This().execute(new Void[0]);
    }

    public String getServerConfiguration() throws IOException {
        Request.Builder builder = new Request.Builder();
        builder.url(DEFAULT_REAL_TIME_DATA_HOST);
        builder.post(RequestBody.create(MediaType.parse("text/plain"), ""));
        builder.header("User-Agent", "android-websockets-2.0");
        return this.mOkHttpClient.newCall(builder.build()).execute().body().string();
    }

    private void newWebSocket(String session, final of onNewWebsocketListener) {
        Request.Builder builder = new Request.Builder();
        final String createSecret = createSecret();
        cn.bmob.v3.util.thing.Code("key:" + createSecret);
        builder.url("http://io.bmob.cn:3010/socket.io/1/websocket/" + session);
        builder.header("GET", "HTTP/1.1");
        builder.header("Upgrade", PROTOCOL_WEBSOCKET);
        builder.header("Connection", "Upgrade");
        builder.header("Host", "io.bmob.cn");
        builder.header("Origin", "http://io.bmob.cn");
        builder.header("User-Agent", "android-websockets-2.0");
        builder.header("Sec-WebSocket-Key", createSecret);
        builder.header("Sec-WebSocket-Version", "13");
        this.mOkHttpClient.newWebSocket(builder.build(), new WebSocketListener() {
            @Override
            public final void onOpen(WebSocket webSocket, Response response) {
                super.onOpen(webSocket, response);
                cn.bmob.v3.util.thing.Code("onOpen:" + response.message());
                Headers headers = response.headers();
                cn.bmob.v3.util.thing.Code("onOpen:" + headers.toString());
                try {
                    cn.bmob.v3.util.thing.Code("onOpen:" + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                String expectedKey = Client.this.expectedKey(createSecret);
                cn.bmob.v3.util.thing.Code("onOpen:" + expectedKey);
            }

            @Override
            public final void onMessage(WebSocket webSocket, String text) {
                super.onMessage(webSocket, text);
                try {
                    Client.this.handleMessage(webSocket, text, onNewWebsocketListener);
                } catch (JSONException e) {
                    onNewWebsocketListener.Code(e);
                    e.printStackTrace();
                }
            }

            @Override
            public final void onMessage(WebSocket webSocket, ByteString bytes) {
                super.onMessage(webSocket, bytes);
            }

            @Override
            public final void onClosing(WebSocket webSocket, int code, String reason) {
                super.onClosing(webSocket, code, reason);
                cn.bmob.v3.util.thing.Code("onClosing:" + reason);
            }

            @Override
            public final void onClosed(WebSocket webSocket, int code, String reason) {
                super.onClosed(webSocket, code, reason);
                cn.bmob.v3.util.thing.Code("onClosed:" + reason);
            }

            @Override
            public final void onFailure(WebSocket webSocket, Throwable t, Response response) {
                super.onFailure(webSocket, t, response);
                cn.bmob.v3.util.thing.Code("onFailure:" + t.getMessage());
                onNewWebsocketListener.Code(new Exception(t));
            }
        });
    }

    public void handleMessage(WebSocket webSocket, String text, of onNewWebsocketListener) throws JSONException {
        cn.bmob.v3.util.thing.Code("onMessage:" + text);
        String[] split = text.split(":", 4);
        switch (Integer.parseInt(split[0])) {
            case 0:
                onNewWebsocketListener.Code();
                return;
            case 1:
                onNewWebsocketListener.Code(webSocket);
                return;
            case 2:
                send("2::");
                onNewWebsocketListener.V();
                return;
            case 3:
                return;
            case 4:
                new JSONObject(split[3]);
                return;
            case 5:
                JSONObject jSONObject = new JSONObject(split[3]);
                String string = jSONObject.getString("name");
                JSONArray optJSONArray = jSONObject.optJSONArray("args");
                cn.bmob.v3.util.thing.Code(string);
                if (string.equals("server_pub")) {
                    cn.bmob.v3.util.thing.Code(string);
                    onNewWebsocketListener.Code(new JSONObject(optJSONArray.getString(0)));
                    return;
                }
                return;
            case 6:
                String[] split2 = split[3].split("\\+", 2);
                JSONArray jSONArray = null;
                if (split2.length == 2) {
                    jSONArray = new JSONArray(split2[1]);
                }
                String str = "";
                if (jSONArray != null) {
                    str = "+" + jSONArray.toString();
                }
                webSocket.send(String.format("6:::%s%s", split[1], str));
                return;
            case 7:
                onNewWebsocketListener.Code(split[2], split[3]);
                return;
            default:
                return;
        }
    }

    private String createSecret() {
        byte[] bArr = new byte[16];
        for (int i = 0; i < 16; i++) {
            bArr[i] = (byte) (Math.random() * 256.0d);
        }
        return Base64.encodeToString(bArr, 0).trim();
    }

    public String expectedKey(String secret) {
        try {
            return Base64.encodeToString(MessageDigest.getInstance("SHA-1").digest((secret + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes()), 0).trim();
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    public void emitRaw(int type, String message) {
        StringBuilder sb = new StringBuilder();
        int i = this.ackCount;
        this.ackCount = i + 1;
        sb.append(i);
        String sb2 = sb.toString();
        String format = String.format("%d:%s:%s:%s", Integer.valueOf(type), sb2 + "+", "", message);
        StringBuilder sb3 = new StringBuilder("客户端发送:");
        sb3.append(format);
        cn.bmob.v3.util.thing.Code(sb3.toString());
        send(format);
    }

    public void send(String text) {
        cn.bmob.v3.util.thing.Code("send:" + text);
        this.mWebSocket.send(text);
    }

    public void subTableUpdate(String tableName) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, "", "updateTable").toString());
        emit("client_sub", jSONArray);
    }

    public void unsubTableUpdate(String tableName) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, "", "unsub_updateTable").toString());
        emit("client_unsub", jSONArray);
    }

    public void subTableDelete(String tableName) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, "", "deleteTable").toString());
        emit("client_sub", jSONArray);
    }

    public void unsubTableDelete(String tableName) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, "", "unsub_deleteTable").toString());
        emit("client_unsub", jSONArray);
    }

    public void subRowUpdate(String tableName, String objectId) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, objectId, "updateRow").toString());
        emit("client_sub", jSONArray);
    }

    public void unsubRowUpdate(String tableName, String objectId) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, objectId, "unsub_updateRow").toString());
        emit("client_unsub", jSONArray);
    }

    public void subRowDelete(String tableName, String objectId) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, objectId, "deleteRow").toString());
        emit("client_sub", jSONArray);
    }

    public void unsubRowDelete(String tableName, String objectId) {
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(getArgs(tableName, objectId, "unsub_deleteRow").toString());
        emit("client_unsub", jSONArray);
    }

    private JSONObject getArgs(String tableName, String objectId, String action) {
        JSONObject jSONObject = new JSONObject();
        try {
            jSONObject.put("appKey", BmobNative.getAppId());
            jSONObject.put("tableName", tableName);
            jSONObject.put("objectId", objectId);
            jSONObject.put("action", action);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jSONObject;
    }

    public void emit(String name, JSONArray args) {
        JSONObject jSONObject = new JSONObject();
        try {
            jSONObject.put("name", name);
            jSONObject.put("args", args);
            emitRaw(5, jSONObject.toString());
        } catch (Exception e) {
        }
    }

    class This extends AsyncTask<Void, Void, String> {
        This() {
        }

        @Override
        protected final String doInBackground(Void[] voidArr) {
            return Code();
        }

        @Override
        protected final void onPostExecute(String str) {
            String str2 = str;
            super.onPostExecute(str2);
            if (TextUtils.isEmpty(str2)) {
                Client.this.mClientListener.onConnectCompleted(Client.this, new BmobException((int) ErrorCode.E9015, "Get config failed."));
                return;
            }
            String[] split = str2.split(":");
            if (split.length == 0) {
                ClientListener clientListener = Client.this.mClientListener;
                Client client = Client.this;
                clientListener.onConnectCompleted(client, new BmobException((int) ErrorCode.E9015, "Get config failed:" + str2));
                return;
            }
            final String str3 = split[0];
            String str4 = split[1];
            String str5 = split[3];
            if (!"".equals(str4)) {
                Integer.parseInt(str4);
            }
            if (!new HashSet(Arrays.asList(str5.split(","))).contains(Client.PROTOCOL_WEBSOCKET)) {
                Client.this.mClientListener.onConnectCompleted(Client.this, new BmobException((int) ErrorCode.E9015, "websocket not supported"));
            } else {
                new Thread(new Runnable() {
                    @Override
                    public final void run() {
                        Client.this.listenRealTime(str3);
                    }
                }).start();
            }
        }

        private String Code() {
            try {
                return Client.this.getServerConfiguration();
            } catch (IOException e) {
                return e.getMessage();
            }
        }
    }

    class thing extends Handler {
        private thing() {
        }

        thing(Client client, byte b) {
            this();
        }

        @Override
        public final void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case -1:
                    Client.this.mClientListener.onConnectCompleted(Client.this, (Exception) msg.obj);
                    return;
                case 0:
                    Client.this.mClientListener.onConnectCompleted(Client.this, null);
                    return;
                case 1:
                    Client.this.mClientListener.onConnectCompleted(Client.this, null);
                    return;
                case 2:
                case 3:
                case 4:
                default:
                    return;
                case 5:
                    Client.this.mClientListener.onDataChange(Client.this, (JSONObject) msg.obj);
                    return;
            }
        }
    }

    public void listenRealTime(String session) {
        newWebSocket(session, new of() {
            @Override
            public final void Code(Exception exc) {
                Message message = new Message();
                message.what = -1;
                message.obj = exc;
                Client.this.mListenHandler.sendMessage(message);
            }

            @Override
            public final void Code() {
                Client.this.mWebSocket.send(String.format("0::%s", ""));
                Message message = new Message();
                message.what = 0;
                Client.this.mListenHandler.sendMessage(message);
            }

            @Override
            public final void Code(WebSocket webSocket) {
                Client.this.mWebSocket = webSocket;
                Client.this.mWebSocket.send(String.format("1::%s", ""));
                Message message = new Message();
                message.what = 1;
                Client.this.mListenHandler.sendMessage(message);
            }

            @Override
            public final void V() {
                cn.bmob.v3.util.thing.Code("onHeartbeat");
            }

            @Override
            public final void Code(JSONObject jSONObject) {
                cn.bmob.v3.util.thing.Code("onDataChange");
                Message message = new Message();
                message.what = 5;
                message.obj = jSONObject;
                Client.this.mListenHandler.sendMessage(message);
            }

            @Override
            public final void Code(String str, String str2) {
                Message message = new Message();
                message.what = -1;
                message.obj = new Exception(str + ":" + str2);
                Client.this.mListenHandler.sendMessage(message);
            }
        });
    }
}