openvidu-android: updated to support openvidu-server refactoring

This commit is contained in:
pabloFuente 2021-03-29 11:16:25 +02:00
parent 0752d4edcc
commit ee7994c149
9 changed files with 87 additions and 49 deletions

View File

@ -4,9 +4,6 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT" />
</compositeConfiguration>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -36,7 +36,7 @@ dependencies {
implementation 'com.jakewharton:butterknife:10.2.0'
implementation 'com.squareup.okhttp3:okhttp:4.2.0'
implementation 'com.neovisionaries:nv-websocket-client:2.9'
implementation 'org.webrtc:google-webrtc:1.0.30039'
implementation 'org.webrtc:google-webrtc:1.0.32006'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'

View File

@ -23,4 +23,6 @@
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" />
</manifest>

View File

@ -4,28 +4,31 @@ public final class JsonConstants {
// RPC incoming methods
public static final String PARTICIPANT_JOINED = "participantJoined";
public static final String PARTICIPANT_PUBLISHED = "participantPublished";
public static final String PARTICIPANT_UNPUBLISHED = "participantUnpublished";
public static final String PARTICIPANT_LEFT = "participantLeft";
public static final String PARTICIPANT_PUBLISHED = "participantPublished";
public static final String ICE_CANDIDATE = "iceCandidate";
public static final String PARTICIPANT_UNPUBLISHED = "participantUnpublished";
public static final String PARTICIPANT_EVICTED = "participantEvicted";
public static final String RECORDING_STARTED = "recordingStarted";
public static final String RECORDING_STOPPED = "recordingStopped";
public static final String SEND_MESSAGE = "sendMessage";
public static final String STREAM_PROPERTY_CHANGED = "streamPropertyChanged";
public static final String FILTER_EVENT_DISPATCHED = "filterEventDispatched";
public static final String ICE_CANDIDATE = "iceCandidate";
public static final String MEDIA_ERROR = "mediaError";
// RPC outgoing methods
public static final String PING_METHOD = "ping";
public static final String JOINROOM_METHOD = "joinRoom";
public static final String LEAVEROOM_METHOD = "leaveRoom";
public static final String PUBLISHVIDEO_METHOD = "publishVideo";
public static final String ONICECANDIDATE_METHOD = "onIceCandidate";
public static final String PREPARERECEIVEVIDEO_METHOD = "prepareReceiveVideoFrom";
public static final String RECEIVEVIDEO_METHOD = "receiveVideoFrom";
public static final String UNSUBSCRIBEFROMVIDEO_METHOD = "unsubscribeFromVideo";
public static final String SENDMESSAGE_ROOM_METHOD = "sendMessage";
public static final String UNPUBLISHVIDEO_METHOD = "unpublishVideo";
public static final String STREAMPROPERTYCHANGED_METHOD = "streamPropertyChanged";
public static final String NETWORKQUALITYLEVELCHANGED_METHOD = "networkQualityLevelChanged";
public static final String FORCEDISCONNECT_METHOD = "forceDisconnect";
public static final String FORCEUNPUBLISH_METHOD = "forceUnpublish";
public static final String APPLYFILTER_METHOD = "applyFilter";
@ -33,7 +36,6 @@ public final class JsonConstants {
public static final String REMOVEFILTER_METHOD = "removeFilter";
public static final String ADDFILTEREVENTLISTENER_METHOD = "addFilterEventListener";
public static final String REMOVEFILTEREVENTLISTENER_METHOD = "removeFilterEventListener";
public static final String PING_METHOD = "ping";
public static final String JSON_RPCVERSION = "2.0";

View File

@ -145,13 +145,13 @@ public class Session {
this.remoteParticipants.get(connectionId).setPeerConnection(peerConnection);
}
public void createLocalOffer(MediaConstraints constraints) {
localParticipant.getPeerConnection().createOffer(new CustomSdpObserver("local offer sdp") {
public void createOfferForPublishing(MediaConstraints constraints) {
localParticipant.getPeerConnection().createOffer(new CustomSdpObserver("createOffer") {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
super.onCreateSuccess(sessionDescription);
Log.i("createOffer SUCCESS", sessionDescription.toString());
localParticipant.getPeerConnection().setLocalDescription(new CustomSdpObserver("local set local"), sessionDescription);
localParticipant.getPeerConnection().setLocalDescription(new CustomSdpObserver("createOffer_setLocalDescription"), sessionDescription);
websocket.publishVideo(sessionDescription);
}
@ -163,6 +163,32 @@ public class Session {
}, constraints);
}
public void createAnswerForSubscribing(RemoteParticipant remoteParticipant, String streamId, MediaConstraints constraints) {
remoteParticipant.getPeerConnection().createAnswer(new CustomSdpObserver("createAnswerSubscribing") {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
super.onCreateSuccess(sessionDescription);
Log.i("createAnswer SUCCESS", sessionDescription.toString());
remoteParticipant.getPeerConnection().setLocalDescription(new CustomSdpObserver("createAnswerSubscribing_setLocalDescription") {
@Override
public void onSetSuccess() {
websocket.receiveVideoFrom(sessionDescription, remoteParticipant, streamId);
}
@Override
public void onSetFailure(String s) {
Log.e("setRemoteDescription ER", s);
}
}, sessionDescription);
}
@Override
public void onCreateFailure(String s) {
Log.e("createAnswer ERROR", s);
}
}, constraints);
}
public String getId() {
return this.id;
}

View File

@ -3,6 +3,7 @@ package io.openvidu.openvidu_android.websocket;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.util.Pair;
import android.widget.Toast;
import com.neovisionaries.ws.client.ThreadType;
@ -78,6 +79,7 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
private AtomicInteger ID_JOINROOM = new AtomicInteger(-1);
private AtomicInteger ID_LEAVEROOM = new AtomicInteger(-1);
private AtomicInteger ID_PUBLISHVIDEO = new AtomicInteger(-1);
private Map<Integer, Pair<String, String>> IDS_PREPARERECEIVEVIDEO = new ConcurrentHashMap<>();
private Map<Integer, String> IDS_RECEIVEVIDEO = new ConcurrentHashMap<>();
private Set<Integer> IDS_ONICECANDIDATE = Collections.newSetFromMap(new ConcurrentHashMap<>());
private Session session;
@ -134,7 +136,7 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
MediaConstraints sdpConstraints = new MediaConstraints();
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
session.createLocalOffer(sdpConstraints);
session.createOfferForPublishing(sdpConstraints);
if (result.getJSONArray(JsonConstants.VALUE).length() > 0) {
// There were users already connected to the session
@ -146,21 +148,33 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
if (websocket.isOpen()) {
websocket.disconnect();
}
} else if (rpcId == this.ID_PUBLISHVIDEO.get()) {
// Response to publishVideo
SessionDescription sessionDescription = new SessionDescription(SessionDescription.Type.ANSWER, result.getString("sdpAnswer"));
this.session.getLocalParticipant().getPeerConnection().setRemoteDescription(new CustomSdpObserver("localSetRemoteDesc"), sessionDescription);
LocalParticipant localParticipant = this.session.getLocalParticipant();
SessionDescription remoteSdpAnswer = new SessionDescription(SessionDescription.Type.ANSWER, result.getString("sdpAnswer"));
localParticipant.getPeerConnection().setRemoteDescription(new CustomSdpObserver("publishVideo_setRemoteDescription"), remoteSdpAnswer);
} else if (this.IDS_PREPARERECEIVEVIDEO.containsKey(rpcId)) {
// Response to prepareReceiveVideoFrom
Pair<String, String> participantAndStream = IDS_PREPARERECEIVEVIDEO.remove(rpcId);
RemoteParticipant remoteParticipant = session.getRemoteParticipant(participantAndStream.first);
String streamId = participantAndStream.second;
SessionDescription remoteSdpOffer = new SessionDescription(SessionDescription.Type.OFFER, result.getString("sdpOffer"));
remoteParticipant.getPeerConnection().setRemoteDescription(new CustomSdpObserver("prepareReceiveVideoFrom_setRemoteDescription") {
@Override
public void onSetSuccess() {
subscribeAux(remoteParticipant, streamId);
}
@Override
public void onSetFailure(String s) {
Log.i("setRemoteDescription ER", s);
}
}, remoteSdpOffer);
} else if (this.IDS_RECEIVEVIDEO.containsKey(rpcId)) {
// Response to receiveVideoFrom
SessionDescription sessionDescription = new SessionDescription(SessionDescription.Type.ANSWER, result.getString("sdpAnswer"));
session.getRemoteParticipant(IDS_RECEIVEVIDEO.remove(rpcId)).getPeerConnection().setRemoteDescription(new CustomSdpObserver("remoteSetRemoteDesc"), sessionDescription);
IDS_RECEIVEVIDEO.remove(rpcId);
} else if (this.IDS_ONICECANDIDATE.contains(rpcId)) {
// Response to onIceCandidate
IDS_ONICECANDIDATE.remove(rpcId);
} else {
Log.e(TAG, "Unrecognized server response: " + result);
}
@ -194,10 +208,16 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
this.ID_PUBLISHVIDEO.set(this.sendJson(JsonConstants.PUBLISHVIDEO_METHOD, publishVideoParams));
}
public void prepareReceiveVideoFrom(RemoteParticipant remoteParticipant, String streamId) {
Map<String, String> prepareReceiveVideoFromParams = new HashMap<>();
prepareReceiveVideoFromParams.put("sender", streamId);
this.IDS_PREPARERECEIVEVIDEO.put(this.sendJson(JsonConstants.PREPARERECEIVEVIDEO_METHOD, prepareReceiveVideoFromParams), new Pair<>(remoteParticipant.getConnectionId(), streamId));
}
public void receiveVideoFrom(SessionDescription sessionDescription, RemoteParticipant remoteParticipant, String streamId) {
Map<String, String> receiveVideoFromParams = new HashMap<>();
receiveVideoFromParams.put("sdpOffer", sessionDescription.description);
receiveVideoFromParams.put("sender", streamId);
receiveVideoFromParams.put("sdpAnswer", sessionDescription.description);
this.IDS_RECEIVEVIDEO.put(this.sendJson(JsonConstants.RECEIVEVIDEO_METHOD, receiveVideoFromParams), remoteParticipant.getConnectionId());
}
@ -254,7 +274,7 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
jsonObject.put("id", id);
jsonObject.put("params", paramsJson);
} catch (JSONException e) {
Log.i(TAG, "JSONException raised on sendJson", e);
Log.e(TAG, "JSONException raised on sendJson", e);
return -1;
}
this.websocket.sendText(jsonObject.toString());
@ -272,7 +292,7 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
for (int j = 0; j < streams.length(); j++) {
JSONObject stream = streams.getJSONObject(0);
String streamId = stream.getString("id");
this.subscribeAux(remoteParticipant, streamId);
this.prepareSubscriptionAux(remoteParticipant, streamId);
}
} catch (Exception e) {
//Sometimes when we enter in room the other participants have no stream
@ -314,7 +334,7 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
String remoteParticipantId = params.getString(JsonConstants.ID);
final RemoteParticipant remoteParticipant = this.session.getRemoteParticipant(remoteParticipantId);
final String streamId = params.getJSONArray("streams").getJSONObject(0).getString("id");
this.subscribeAux(remoteParticipant, streamId);
this.prepareSubscriptionAux(remoteParticipant, streamId);
}
private void participantLeftEvent(JSONObject params) throws JSONException {
@ -346,24 +366,15 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
return remoteParticipant;
}
private void prepareSubscriptionAux(RemoteParticipant remoteParticipant, String streamId) {
prepareReceiveVideoFrom(remoteParticipant, streamId);
}
private void subscribeAux(RemoteParticipant remoteParticipant, String streamId) {
MediaConstraints sdpConstraints = new MediaConstraints();
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
remoteParticipant.getPeerConnection().createOffer(new CustomSdpObserver("remote offer sdp") {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
super.onCreateSuccess(sessionDescription);
remoteParticipant.getPeerConnection().setLocalDescription(new CustomSdpObserver("remoteSetLocalDesc"), sessionDescription);
receiveVideoFrom(sessionDescription, remoteParticipant, streamId);
}
@Override
public void onCreateFailure(String s) {
Log.e("createOffer error", s);
}
}, sdpConstraints);
this.session.createAnswerForSubscribing(remoteParticipant, streamId, sdpConstraints);
}
public void setWebsocketCancelled(boolean websocketCancelled) {
@ -478,43 +489,43 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
@Override
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
Log.i(TAG, "Error!");
Log.e(TAG, "Error!");
}
@Override
public void onFrameError(WebSocket websocket, WebSocketException cause, WebSocketFrame
frame) throws Exception {
Log.i(TAG, "Frame error!");
Log.e(TAG, "Frame error!");
}
@Override
public void onMessageError(WebSocket websocket, WebSocketException
cause, List<WebSocketFrame> frames) throws Exception {
Log.i(TAG, "Message error! " + cause);
Log.e(TAG, "Message error! " + cause);
}
@Override
public void onMessageDecompressionError(WebSocket websocket, WebSocketException cause,
byte[] compressed) throws Exception {
Log.i(TAG, "Message decompression error!");
Log.e(TAG, "Message decompression error!");
}
@Override
public void onTextMessageError(WebSocket websocket, WebSocketException cause, byte[] data) throws
Exception {
Log.i(TAG, "Text message error! " + cause);
Log.e(TAG, "Text message error! " + cause);
}
@Override
public void onSendError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws
Exception {
Log.i(TAG, "Send error! " + cause);
Log.e(TAG, "Send error! " + cause);
}
@Override
public void onUnexpectedError(WebSocket websocket, WebSocketException cause) throws
Exception {
Log.i(TAG, "Unexpected error! " + cause);
Log.e(TAG, "Unexpected error! " + cause);
}
@Override

View File

@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath 'com.android.tools.build:gradle:4.1.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -1,6 +1,6 @@
#Tue Sep 10 10:08:16 CEST 2019
#Thu Mar 25 18:51:34 CET 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip