Skip to content

Commit e1ffafc

Browse files
UberMCTrent Ewaldslycoder
authoredApr 12, 2020
dataTrack support added. (blackuy#268)
* dataTrack support added. onDataTrackMessageReceived, sendString, onParticipantAddedDataTrack, onParticipantRemovedDataTrack iOS and android tested. * bump version yarn cache * onDestroy cleanup dataTrackMessageThread. Remove debug messages, add toDO and log on didReceiveData Co-authored-by: Trent Ewald <trent@caribu.com> Co-authored-by: Jonathan Chang <slycoder@gmail.com>
1 parent 58e7659 commit e1ffafc

File tree

7 files changed

+262
-11
lines changed

7 files changed

+262
-11
lines changed
 

‎android/build.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ android {
99
compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION
1010
buildToolsVersion rootProject.hasProperty('buildToolsVersion') ? rootProject.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION
1111

12+
compileOptions {
13+
sourceCompatibility JavaVersion.VERSION_1_8
14+
targetCompatibility JavaVersion.VERSION_1_8
15+
}
1216
defaultConfig {
1317
minSdkVersion 16
1418
targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION

‎android/src/main/java/com/twiliorn/library/CustomTwilioVideoView.java

+123-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
*/
99
package com.twiliorn.library;
1010

11+
import java.nio.ByteBuffer;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
1115
import android.content.BroadcastReceiver;
1216
import android.content.Context;
1317
import android.content.Intent;
@@ -17,6 +21,7 @@
1721
import android.media.AudioManager;
1822
import android.os.Build;
1923
import android.os.Handler;
24+
import android.os.HandlerThread;
2025
import android.support.annotation.NonNull;
2126
import android.support.annotation.StringDef;
2227
import android.util.Log;
@@ -43,6 +48,7 @@
4348
import com.twilio.video.RemoteAudioTrack;
4449
import com.twilio.video.RemoteAudioTrackPublication;
4550
import com.twilio.video.RemoteAudioTrackStats;
51+
import com.twilio.video.LocalDataTrack;
4652
import com.twilio.video.RemoteDataTrack;
4753
import com.twilio.video.RemoteDataTrackPublication;
4854
import com.twilio.video.RemoteParticipant;
@@ -73,6 +79,8 @@
7379
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_CONNECTED;
7480
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_CONNECT_FAILURE;
7581
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_DISCONNECTED;
82+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_DATATRACK_MESSAGE_RECEIVED;
83+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ADDED_DATA_TRACK;
7684
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ADDED_AUDIO_TRACK;
7785
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ADDED_VIDEO_TRACK;
7886
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_CONNECTED;
@@ -81,13 +89,15 @@
8189
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_DISCONNECTED;
8290
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ENABLED_AUDIO_TRACK;
8391
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ENABLED_VIDEO_TRACK;
92+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_DATA_TRACK;
8493
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_AUDIO_TRACK;
8594
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_VIDEO_TRACK;
8695
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_STATS_RECEIVED;
8796
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_VIDEO_CHANGED;
8897

8998
public class CustomTwilioVideoView extends View implements LifecycleEventListener, AudioManager.OnAudioFocusChangeListener {
9099
private static final String TAG = "CustomTwilioVideoView";
100+
private static final String DATA_TRACK_MESSAGE_THREAD_NAME = "DataTrackMessages";
91101
private boolean enableRemoteAudio = false;
92102

93103
@Retention(RetentionPolicy.SOURCE)
@@ -100,6 +110,9 @@ public class CustomTwilioVideoView extends View implements LifecycleEventListene
100110
Events.ON_PARTICIPANT_CONNECTED,
101111
Events.ON_PARTICIPANT_DISCONNECTED,
102112
Events.ON_PARTICIPANT_ADDED_VIDEO_TRACK,
113+
Events.ON_DATATRACK_MESSAGE_RECEIVED,
114+
Events.ON_PARTICIPANT_ADDED_DATA_TRACK,
115+
Events.ON_PARTICIPANT_REMOVED_DATA_TRACK,
103116
Events.ON_PARTICIPANT_REMOVED_VIDEO_TRACK,
104117
Events.ON_PARTICIPANT_ADDED_AUDIO_TRACK,
105118
Events.ON_PARTICIPANT_REMOVED_AUDIO_TRACK,
@@ -117,6 +130,9 @@ public class CustomTwilioVideoView extends View implements LifecycleEventListene
117130
String ON_DISCONNECTED = "onRoomDidDisconnect";
118131
String ON_PARTICIPANT_CONNECTED = "onRoomParticipantDidConnect";
119132
String ON_PARTICIPANT_DISCONNECTED = "onRoomParticipantDidDisconnect";
133+
String ON_DATATRACK_MESSAGE_RECEIVED = "onDataTrackMessageReceived";
134+
String ON_PARTICIPANT_ADDED_DATA_TRACK = "onParticipantAddedDataTrack";
135+
String ON_PARTICIPANT_REMOVED_DATA_TRACK = "onParticipantRemovedDataTrack";
120136
String ON_PARTICIPANT_ADDED_VIDEO_TRACK = "onParticipantAddedVideoTrack";
121137
String ON_PARTICIPANT_REMOVED_VIDEO_TRACK = "onParticipantRemovedVideoTrack";
122138
String ON_PARTICIPANT_ADDED_AUDIO_TRACK = "onParticipantAddedAudioTrack";
@@ -158,6 +174,17 @@ public class CustomTwilioVideoView extends View implements LifecycleEventListene
158174
private IntentFilter intentFilter;
159175
private BecomingNoisyReceiver myNoisyAudioStreamReceiver;
160176

177+
// Dedicated thread and handler for messages received from a RemoteDataTrack
178+
private final HandlerThread dataTrackMessageThread =
179+
new HandlerThread(DATA_TRACK_MESSAGE_THREAD_NAME);
180+
private Handler dataTrackMessageThreadHandler;
181+
182+
private LocalDataTrack localDataTrack;
183+
184+
// Map used to map remote data tracks to remote participants
185+
private final Map<RemoteDataTrack, RemoteParticipant> dataTrackRemoteParticipantMap =
186+
new HashMap<>();
187+
161188
public CustomTwilioVideoView(ThemedReactContext context) {
162189
super(context);
163190
this.themedReactContext = context;
@@ -178,6 +205,15 @@ public CustomTwilioVideoView(ThemedReactContext context) {
178205
audioManager = (AudioManager) themedReactContext.getSystemService(Context.AUDIO_SERVICE);
179206
myNoisyAudioStreamReceiver = new BecomingNoisyReceiver();
180207
intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
208+
209+
// Create the local data track
210+
// localDataTrack = LocalDataTrack.create(this);
211+
localDataTrack = LocalDataTrack.create(getContext());
212+
213+
// Start the thread where data messages are received
214+
dataTrackMessageThread.start();
215+
dataTrackMessageThreadHandler = new Handler(dataTrackMessageThread.getLooper());
216+
181217
}
182218

183219
// ===== SETUP =================================================================================
@@ -247,6 +283,7 @@ private void createLocalMedia(boolean enableAudio, boolean enableVideo) {
247283

248284
// ===== LIFECYCLE EVENTS ======================================================================
249285

286+
250287
@Override
251288
public void onHostResume() {
252289
/*
@@ -322,6 +359,11 @@ public void onHostDestroy() {
322359
localAudioTrack.release();
323360
localAudioTrack = null;
324361
}
362+
363+
// Quit the data track message thread
364+
dataTrackMessageThread.quit();
365+
366+
325367
}
326368

327369
public void releaseResource() {
@@ -367,6 +409,12 @@ public void connectToRoom(boolean enableAudio) {
367409
connectOptionsBuilder.videoTracks(Collections.singletonList(localVideoTrack));
368410
}
369411

412+
//LocalDataTrack localDataTrack = LocalDataTrack.create(getContext());
413+
414+
if (localDataTrack != null) {
415+
connectOptionsBuilder.dataTracks(Collections.singletonList(localDataTrack));
416+
}
417+
370418
room = Video.connect(getContext(), connectOptionsBuilder.build(), roomListener());
371419
}
372420

@@ -455,6 +503,13 @@ public void disconnect() {
455503
}
456504
}
457505

506+
// ===== SEND STRING ON DATA TRACK ======================================================================
507+
public void sendString(String message) {
508+
if (localDataTrack != null) {
509+
localDataTrack.send(message);
510+
}
511+
}
512+
458513
// ===== BUTTON LISTENERS ======================================================================
459514
private static void setThumbnailMirror() {
460515
if (cameraCapturer != null) {
@@ -643,6 +698,7 @@ private Room.Listener roomListener() {
643698
@Override
644699
public void onConnected(Room room) {
645700
localParticipant = room.getLocalParticipant();
701+
646702
WritableMap event = new WritableNativeMap();
647703
event.putString("roomName", room.getName());
648704
event.putString("roomSid", room.getSid());
@@ -656,6 +712,10 @@ public void onConnected(Room room) {
656712

657713
pushEvent(CustomTwilioVideoView.this, ON_CONNECTED, event);
658714

715+
716+
//There is not .publish it's publishTrack
717+
localParticipant.publishTrack(localDataTrack);
718+
659719
for (RemoteParticipant participant : participants) {
660720
addParticipant(room, participant);
661721
}
@@ -706,6 +766,7 @@ public void onDisconnected(Room room, TwilioException e) {
706766
@Override
707767
public void onParticipantConnected(Room room, RemoteParticipant participant) {
708768
addParticipant(room, participant);
769+
709770
}
710771

711772
@Override
@@ -726,19 +787,31 @@ public void onRecordingStopped(Room room) {
726787
/*
727788
* Called when participant joins the room
728789
*/
729-
private void addParticipant(Room room, RemoteParticipant participant) {
790+
private void addParticipant(Room room, RemoteParticipant remoteParticipant) {
730791

731792
WritableMap event = new WritableNativeMap();
732793
event.putString("roomName", room.getName());
733794
event.putString("roomSid", room.getSid());
734-
event.putMap("participant", buildParticipant(participant));
795+
event.putMap("participant", buildParticipant(remoteParticipant));
735796

736797
pushEvent(this, ON_PARTICIPANT_CONNECTED, event);
737798

738799
/*
739800
* Start listening for participant media events
740801
*/
741-
participant.setListener(mediaListener());
802+
remoteParticipant.setListener(mediaListener());
803+
804+
for (final RemoteDataTrackPublication remoteDataTrackPublication :
805+
remoteParticipant.getRemoteDataTracks()) {
806+
/*
807+
* Data track messages are received on the thread that calls setListener. Post the
808+
* invocation of setting the listener onto our dedicated data track message thread.
809+
*/
810+
if (remoteDataTrackPublication.isTrackSubscribed()) {
811+
dataTrackMessageThreadHandler.post(() -> addRemoteDataTrack(remoteParticipant,
812+
remoteDataTrackPublication.getRemoteDataTrack()));
813+
}
814+
}
742815
}
743816

744817
/*
@@ -754,6 +827,10 @@ private void removeParticipant(Room room, RemoteParticipant participant) {
754827
//participant.setListener(null);
755828
}
756829

830+
private void addRemoteDataTrack(RemoteParticipant remoteParticipant, RemoteDataTrack remoteDataTrack) {
831+
dataTrackRemoteParticipantMap.put(remoteDataTrack, remoteParticipant);
832+
remoteDataTrack.setListener(remoteDataTrackListener());
833+
}
757834

758835
// ====== MEDIA LISTENER =======================================================================
759836

@@ -786,14 +863,19 @@ public void onAudioTrackUnpublished(RemoteParticipant participant, RemoteAudioTr
786863

787864
}
788865

789-
@Override
790-
public void onDataTrackSubscribed(RemoteParticipant participant, RemoteDataTrackPublication publication, RemoteDataTrack dataTrack) {
791866

792-
}
793867

794868
@Override
795-
public void onDataTrackUnsubscribed(RemoteParticipant participant, RemoteDataTrackPublication publication, RemoteDataTrack dataTrack) {
869+
public void onDataTrackSubscribed(RemoteParticipant remoteParticipant, RemoteDataTrackPublication remoteDataTrackPublication, RemoteDataTrack remoteDataTrack) {
870+
WritableMap event = buildParticipantDataEvent(remoteParticipant);
871+
pushEvent(CustomTwilioVideoView.this, ON_PARTICIPANT_ADDED_DATA_TRACK, event);
872+
dataTrackMessageThreadHandler.post(() -> addRemoteDataTrack(remoteParticipant, remoteDataTrack));
873+
}
796874

875+
@Override
876+
public void onDataTrackUnsubscribed(RemoteParticipant remoteParticipant, RemoteDataTrackPublication publication, RemoteDataTrack remoteDataTrack) {
877+
WritableMap event = buildParticipantDataEvent(remoteParticipant);
878+
pushEvent(CustomTwilioVideoView.this, ON_PARTICIPANT_REMOVED_DATA_TRACK, event);
797879
}
798880

799881
@Override
@@ -869,6 +951,17 @@ private WritableMap buildParticipant(Participant participant) {
869951
return participantMap;
870952
}
871953

954+
955+
private WritableMap buildParticipantDataEvent(Participant participant) {
956+
WritableMap participantMap = buildParticipant(participant);
957+
WritableMap participantMap2 = buildParticipant(participant);
958+
959+
WritableMap event = new WritableNativeMap();
960+
event.putMap("participant", participantMap);
961+
event.putMap("track", participantMap2);
962+
return event;
963+
}
964+
872965
private WritableMap buildParticipantVideoEvent(Participant participant, TrackPublication publication) {
873966
WritableMap participantMap = buildParticipant(participant);
874967

@@ -883,6 +976,12 @@ private WritableMap buildParticipantVideoEvent(Participant participant, TrackPub
883976
return event;
884977
}
885978

979+
private WritableMap buildDataTrackEvent(String message) {
980+
WritableMap event = new WritableNativeMap();
981+
event.putString("message", message);
982+
return event;
983+
}
984+
886985
private void addParticipantVideo(Participant participant, RemoteVideoTrackPublication publication) {
887986
WritableMap event = this.buildParticipantVideoEvent(participant, publication);
888987
pushEvent(CustomTwilioVideoView.this, ON_PARTICIPANT_ADDED_VIDEO_TRACK, event);
@@ -924,4 +1023,21 @@ public static void registerThumbnailVideoView(VideoView v) {
9241023
}
9251024
setThumbnailMirror();
9261025
}
1026+
1027+
private RemoteDataTrack.Listener remoteDataTrackListener() {
1028+
return new RemoteDataTrack.Listener() {
1029+
1030+
@Override
1031+
public void onMessage(RemoteDataTrack remoteDataTrack, ByteBuffer byteBuffer) {
1032+
1033+
}
1034+
1035+
1036+
@Override
1037+
public void onMessage(RemoteDataTrack remoteDataTrack, String message) {
1038+
WritableMap event = buildDataTrackEvent(message);
1039+
pushEvent(CustomTwilioVideoView.this, ON_DATATRACK_MESSAGE_RECEIVED, event);
1040+
}
1041+
};
1042+
}
9271043
}

‎android/src/main/java/com/twiliorn/library/CustomTwilioVideoViewManager.java

+15
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_CONNECTED;
2727
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_DISCONNECTED;
2828
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_VIDEO_CHANGED;
29+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_DATA_TRACK;
30+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ADDED_DATA_TRACK;
31+
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_DATATRACK_MESSAGE_RECEIVED;
2932
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ADDED_VIDEO_TRACK;
3033
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_VIDEO_TRACK;
3134
import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_ADDED_AUDIO_TRACK;
@@ -51,6 +54,7 @@ public class CustomTwilioVideoViewManager extends SimpleViewManager<CustomTwilio
5154
private static final int TOGGLE_REMOTE_SOUND = 9;
5255
private static final int RELEASE_RESOURCE = 10;
5356
private static final int TOGGLE_BLUETOOTH_HEADSET = 11;
57+
private static final int SEND_STRING = 12;
5458

5559
@Override
5660
public String getName() {
@@ -108,6 +112,9 @@ public void receiveCommand(CustomTwilioVideoView view, int commandId, @Nullable
108112
Boolean headsetEnabled = args.getBoolean(0);
109113
view.toggleBluetoothHeadset(headsetEnabled);
110114
break;
115+
case SEND_STRING:
116+
view.sendString(args.getString(0));
117+
break;
111118
}
112119
}
113120

@@ -126,11 +133,18 @@ public Map getExportedCustomDirectEventTypeConstants() {
126133

127134
map.putAll(MapBuilder.of(
128135
ON_PARTICIPANT_DISCONNECTED, MapBuilder.of("registrationName", ON_PARTICIPANT_DISCONNECTED),
136+
ON_DATATRACK_MESSAGE_RECEIVED, MapBuilder.of("registrationName", ON_DATATRACK_MESSAGE_RECEIVED),
137+
ON_PARTICIPANT_ADDED_DATA_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_ADDED_DATA_TRACK),
129138
ON_PARTICIPANT_ADDED_VIDEO_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_ADDED_VIDEO_TRACK),
130139
ON_PARTICIPANT_REMOVED_VIDEO_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_REMOVED_VIDEO_TRACK),
131140
ON_PARTICIPANT_ADDED_AUDIO_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_ADDED_AUDIO_TRACK),
132141
ON_PARTICIPANT_REMOVED_AUDIO_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_REMOVED_AUDIO_TRACK)
133142
));
143+
144+
map.putAll(MapBuilder.of(
145+
ON_PARTICIPANT_REMOVED_DATA_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_REMOVED_DATA_TRACK)
146+
));
147+
134148
map.putAll(MapBuilder.of(
135149
ON_PARTICIPANT_ENABLED_VIDEO_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_ENABLED_VIDEO_TRACK),
136150
ON_PARTICIPANT_DISABLED_VIDEO_TRACK, MapBuilder.of("registrationName", ON_PARTICIPANT_DISABLED_VIDEO_TRACK),
@@ -155,6 +169,7 @@ public Map<String, Integer> getCommandsMap() {
155169
.put("disableOpenSLES", DISABLE_OPENSL_ES)
156170
.put("toggleRemoteSound", TOGGLE_REMOTE_SOUND)
157171
.put("toggleBluetoothHeadset", TOGGLE_BLUETOOTH_HEADSET)
172+
.put("sendString", SEND_STRING)
158173
.build();
159174
}
160175
}

0 commit comments

Comments
 (0)
Failed to load comments.