Sample code
package com.cylan.artcsdk;
import android.util.Log;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
public class ARtcService {
private static final String TAG = "ARtcService";
private String mServerUrl;
private String mUid;
private ARtcState mState = ARtcState.none;
private Observer mObserver;
private WebSocketClient mSignal;
Timer time;
private final HashMap<String, SessionInfo> mSessions;
private static class SessionInfo {
public List<String> queueCandidates;
public WeakReference<ARtcSession> wkSession;
public SessionInfo() {
queueCandidates = new ArrayList<>();
}
}
public interface Observer {
void onRemoteCall(String peerId, String peerCallInfo, String permitCode);
void onStateChanged(ARtcState state, int value, String msg);
}
public ARtcService() {
mSessions = new HashMap<>();
}
public void connectToServer(String url, Observer observer) {
this.mObserver = observer;
mServerUrl = url + "/im";
if (mSignal != null) {
Log.d(TAG, "signal not empty");
return;
}
Log.i(TAG, "connect to " + url);
mState = ARtcState.connecting;
connectInternal(mServerUrl);
}
public void close(String peerId) {
if (mSignal == null) {
return;
}
mSessions.get(peerId).wkSession.get().closePeer();
try {
JSONObject json = new JSONObject();
json.put("opcode", "signout");
if (mState == ARtcState.connected) {
mSignal.send(json.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
mState = ARtcState.closed;
mSignal.close();
mSignal = null;
time.cancel();
time = null;
}
public ARtcState getState() {
return mState;
}
public String getUid() {
return mUid;
}
public void addSession(String peerId, ARtcSession session) {
synchronized (mSessions) {
SessionInfo si = new SessionInfo();
si.wkSession = new WeakReference<>(session);
mSessions.put(peerId, si);
for (int i = 0; i < si.queueCandidates.size(); i++) {
session.addRemoteCandidate(si.queueCandidates.get(i));
}
si.queueCandidates.clear();
}
}
public void removeSession(String peerId) {
synchronized (mSessions) {
if (!mSessions.containsKey(peerId)) {
mSessions.remove(peerId);
return;
}
Log.e(TAG, "remove session with peerId:" + peerId + " failed");
}
}
public void sendMessage(String message) {
if (mState != ARtcState.connected) {
Log.w(TAG, "sendMessage failed, state:" + mState);
return;
}
mSignal.send(message);
}
private void reportState(ARtcState state) {
mObserver.onStateChanged(state, 0, "");
}
private void reportError(int errCode, String msg) {
mObserver.onStateChanged(ARtcState.failed, errCode, msg);
}
private void connectInternal(String url) {
try {
URI uri = new URI(url);
Map<String, String> map = new HashMap<>();
String originUrl = "http" + url.substring(url.indexOf(':'));
map.put("Origin", originUrl);
Log.i(TAG, "originUrl is:" + originUrl);
mSignal = new WebSocketClient(uri, new Draft_6455(), map) {
@Override
public void onOpen(ServerHandshake handshakedata) {
Log.i(TAG, "Connected to server");
keepHeartBeatAlive();
try {
JSONObject json = new JSONObject();
json.put("opcode", "signin");
json.put("key", Constants.key);
json.put("secret", Constants.secrect);
json.put("loginType", 0);
mSignal.send(json.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onMessage(String message) {
Log.i(TAG, "Received message: " + message);
boolean ret = handleMessage(message);
if (!ret) {
mState = ARtcState.failed;
Log.e(TAG, "JSON parse failed. " + message);
mObserver.onStateChanged(mState, -1, "JSON parse failed");
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
if (code != 0) {
if (mState != ARtcState.closed) {
connectInternal(url);
Log.i(TAG, "Connection error reconnecting....., code: " + code + " reason:" + reason);
}
mState = ARtcState.failed;
Log.i(TAG, "Connection error, code: " + code + " reason:" + reason);
} else {
mState = ARtcState.closed;
Log.i(TAG, "Connection closed, code: " + code + " reason:" + reason);
}
mObserver.onStateChanged(mState, code, reason);
}
@Override
public void onError(Exception ex) {
Log.i(TAG, "Connected Error");
}
};
mSignal.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
private static volatile long lastHeartBeat;
private void keepHeartBeatAlive() {
time = new Timer();
time.schedule(new TimerTask() {
@Override
public void run() {
while (mSignal != null) {
if (System.currentTimeMillis() - lastHeartBeat > 60 * 1000L) {
lastHeartBeat = System.currentTimeMillis();
sendHeartBeat();
}
}
}
}, 0L);
}
private void sendHeartBeat() {
try {
JSONObject json = new JSONObject();
json.put("opcode", "heartbeat");
mSignal.send(json.toString());
Log.i(TAG, "client send heart beat------> ");
} catch (JSONException e) {
e.printStackTrace();
}
}
private boolean handleMessage(String payload) {
try {
JSONObject root = new JSONObject(payload);
String opcode = root.getString("opcode");
if (opcode.equals("signin")) {
mUid = root.getString("sid");
if (mUid.isEmpty()) {
return false;
}
Log.i(TAG, "signin successed, GOT local uid " + mUid);
mState = ARtcState.connected;
mObserver.onStateChanged(mState, 0, "");
} else if (opcode.equals("message")) {
String peerId = root.getString("serialCode");
String message = root.getString("message");
String messageType = root.getString("messageType");
if (messageType.equals("callRequest")) {
String permitCode = root.getString("permitCode");
mObserver.onRemoteCall(peerId, message, permitCode);
} else if (messageType.equals("callResponse")) {
handleAnswer(peerId, message);
} else if (messageType.equals("remoteCandidate")) {
handleRemoteCandidate(peerId, message);
} else if (messageType.equals("hangup")) {
handleHangUp(peerId, message);
return true;
} else {
Log.w(TAG, "unkown messageType: " + messageType);
return false;
}
} else if (opcode.equals("heartbeat")) {
if (root.getInt("code") == 0) {
Log.i(TAG, "Server response heart ------>");
}
} else {
Log.w(TAG, "unkown opcode: " + opcode);
return false;
}
return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
private void handleAnswer(String peerId, String message) {
ARtcSession session = getPeerSession(peerId);
if (session == null) {
Log.d(TAG, "session not found for: " + peerId);
return;
}
session.setRemoteAnswer(message);
}
private void handleHangUp(String peerId, String message) {
ARtcSession session = getPeerSession(peerId);
session.onDisconnected();
}
private void handleRemoteCandidate(String peerId, String message) {
ARtcSession session = null;
synchronized (mSessions) {
SessionInfo si = getSessionInfo(peerId);
if (si.wkSession == null) {
si.queueCandidates.add(message);
return;
}
session = si.wkSession.get();
if (session == null) {
mSessions.remove(peerId);
Log.d(TAG, "remove invalid session of peerId: " + peerId);
return;
}
}
session.addRemoteCandidate(message);
}
private SessionInfo getSessionInfo(String peerId) {
SessionInfo si = mSessions.get(peerId);
if (si == null) {
si = new SessionInfo();
mSessions.put(peerId, si);
}
return si;
}
private ARtcSession getPeerSession(String peerId) {
synchronized (mSessions) {
SessionInfo si = mSessions.get(peerId);
if (si == null) {
si = new SessionInfo();
mSessions.put(peerId, si);
}
if (si.wkSession == null) {
return null;
}
ARtcSession session = si.wkSession.get();
if (session == null) {
mSessions.remove(peerId);
Log.d(TAG, "remove invalid session of peerId: " + peerId);
return null;
}
return session;
}
}
}