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);
}
});
}
}