react-native-altibbi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +190 -0
  3. package/android/build.gradle +104 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/altibbi/AltibbiModule.kt +18 -0
  8. package/android/src/main/java/com/altibbi/AltibbiPackage.kt +18 -0
  9. package/android/src/main/java/com/altibbi/OTCustomAudioDevice.java +1146 -0
  10. package/android/src/main/java/com/altibbi/OTPublisherLayout.java +61 -0
  11. package/android/src/main/java/com/altibbi/OTPublisherViewManager.java +30 -0
  12. package/android/src/main/java/com/altibbi/OTRN.java +101 -0
  13. package/android/src/main/java/com/altibbi/OTScreenCapturer.java +120 -0
  14. package/android/src/main/java/com/altibbi/OTSessionManager.java +1281 -0
  15. package/android/src/main/java/com/altibbi/OTSubscriberLayout.java +68 -0
  16. package/android/src/main/java/com/altibbi/OTSubscriberViewManager.java +30 -0
  17. package/android/src/main/java/com/altibbi/Socket.kt +294 -0
  18. package/android/src/main/java/com/altibbi/SocketEventEmitter.kt +25 -0
  19. package/android/src/main/java/com/altibbi/utils/EventUtils.java +189 -0
  20. package/android/src/main/java/com/altibbi/utils/Utils.java +135 -0
  21. package/ios/Altibbi-Bridging-Header.h +6 -0
  22. package/ios/Altibbi.mm +10 -0
  23. package/ios/Altibbi.swift +4 -0
  24. package/ios/OTCustomAudioDriver.swift +696 -0
  25. package/ios/OTPublisher.m +16 -0
  26. package/ios/OTPublisherManager.swift +21 -0
  27. package/ios/OTPublisherView.swift +28 -0
  28. package/ios/OTRN.swift +27 -0
  29. package/ios/OTScreenCapture.h +27 -0
  30. package/ios/OTScreenCapture.m +171 -0
  31. package/ios/OTSessionManager.m +127 -0
  32. package/ios/OTSessionManager.swift +866 -0
  33. package/ios/OTSubscriber.m +15 -0
  34. package/ios/OTSubscriberManager.swift +21 -0
  35. package/ios/OTSubscriberView.swift +29 -0
  36. package/ios/OpenTokReactNative.h +13 -0
  37. package/ios/OpenTokReactNative.m +13 -0
  38. package/ios/SocketReactNative.m +38 -0
  39. package/ios/SocketReactNative.swift +276 -0
  40. package/ios/Utils/EventUtils.swift +143 -0
  41. package/ios/Utils/Utils.swift +126 -0
  42. package/lib/commonjs/connection.js +200 -0
  43. package/lib/commonjs/connection.js.map +1 -0
  44. package/lib/commonjs/data.js +12 -0
  45. package/lib/commonjs/data.js.map +1 -0
  46. package/lib/commonjs/index.js +275 -0
  47. package/lib/commonjs/index.js.map +1 -0
  48. package/lib/commonjs/scoket.js +245 -0
  49. package/lib/commonjs/scoket.js.map +1 -0
  50. package/lib/commonjs/service.js +21 -0
  51. package/lib/commonjs/service.js.map +1 -0
  52. package/lib/commonjs/types.js +2 -0
  53. package/lib/commonjs/types.js.map +1 -0
  54. package/lib/commonjs/video/OT.js +57 -0
  55. package/lib/commonjs/video/OT.js.map +1 -0
  56. package/lib/commonjs/video/OTError.js +17 -0
  57. package/lib/commonjs/video/OTError.js.map +1 -0
  58. package/lib/commonjs/video/OTPublisher.js +171 -0
  59. package/lib/commonjs/video/OTPublisher.js.map +1 -0
  60. package/lib/commonjs/video/OTSession.js +205 -0
  61. package/lib/commonjs/video/OTSession.js.map +1 -0
  62. package/lib/commonjs/video/OTSubscriber.js +185 -0
  63. package/lib/commonjs/video/OTSubscriber.js.map +1 -0
  64. package/lib/commonjs/video/contexts/OTContext.js +11 -0
  65. package/lib/commonjs/video/contexts/OTContext.js.map +1 -0
  66. package/lib/commonjs/video/helpers/OTHelper.js +92 -0
  67. package/lib/commonjs/video/helpers/OTHelper.js.map +1 -0
  68. package/lib/commonjs/video/helpers/OTPublisherHelper.js +117 -0
  69. package/lib/commonjs/video/helpers/OTPublisherHelper.js.map +1 -0
  70. package/lib/commonjs/video/helpers/OTSessionHelper.js +206 -0
  71. package/lib/commonjs/video/helpers/OTSessionHelper.js.map +1 -0
  72. package/lib/commonjs/video/helpers/OTSubscriberHelper.js +121 -0
  73. package/lib/commonjs/video/helpers/OTSubscriberHelper.js.map +1 -0
  74. package/lib/commonjs/video/index.js +42 -0
  75. package/lib/commonjs/video/index.js.map +1 -0
  76. package/lib/commonjs/video/views/OTPublisherView.js +26 -0
  77. package/lib/commonjs/video/views/OTPublisherView.js.map +1 -0
  78. package/lib/commonjs/video/views/OTSubscriberView.js +25 -0
  79. package/lib/commonjs/video/views/OTSubscriberView.js.map +1 -0
  80. package/lib/module/connection.js +180 -0
  81. package/lib/module/connection.js.map +1 -0
  82. package/lib/module/data.js +6 -0
  83. package/lib/module/data.js.map +1 -0
  84. package/lib/module/index.js +12 -0
  85. package/lib/module/index.js.map +1 -0
  86. package/lib/module/scoket.js +235 -0
  87. package/lib/module/scoket.js.map +1 -0
  88. package/lib/module/service.js +14 -0
  89. package/lib/module/service.js.map +1 -0
  90. package/lib/module/types.js +2 -0
  91. package/lib/module/types.js.map +1 -0
  92. package/lib/module/video/OT.js +49 -0
  93. package/lib/module/video/OT.js.map +1 -0
  94. package/lib/module/video/OTError.js +10 -0
  95. package/lib/module/video/OTError.js.map +1 -0
  96. package/lib/module/video/OTPublisher.js +162 -0
  97. package/lib/module/video/OTPublisher.js.map +1 -0
  98. package/lib/module/video/OTSession.js +195 -0
  99. package/lib/module/video/OTSession.js.map +1 -0
  100. package/lib/module/video/OTSubscriber.js +175 -0
  101. package/lib/module/video/OTSubscriber.js.map +1 -0
  102. package/lib/module/video/contexts/OTContext.js +4 -0
  103. package/lib/module/video/contexts/OTContext.js.map +1 -0
  104. package/lib/module/video/helpers/OTHelper.js +82 -0
  105. package/lib/module/video/helpers/OTHelper.js.map +1 -0
  106. package/lib/module/video/helpers/OTPublisherHelper.js +110 -0
  107. package/lib/module/video/helpers/OTPublisherHelper.js.map +1 -0
  108. package/lib/module/video/helpers/OTSessionHelper.js +195 -0
  109. package/lib/module/video/helpers/OTSessionHelper.js.map +1 -0
  110. package/lib/module/video/helpers/OTSubscriberHelper.js +112 -0
  111. package/lib/module/video/helpers/OTSubscriberHelper.js.map +1 -0
  112. package/lib/module/video/index.js +7 -0
  113. package/lib/module/video/index.js.map +1 -0
  114. package/lib/module/video/views/OTPublisherView.js +18 -0
  115. package/lib/module/video/views/OTPublisherView.js.map +1 -0
  116. package/lib/module/video/views/OTSubscriberView.js +17 -0
  117. package/lib/module/video/views/OTSubscriberView.js.map +1 -0
  118. package/lib/typescript/src/connection.d.ts +40 -0
  119. package/lib/typescript/src/connection.d.ts.map +1 -0
  120. package/lib/typescript/src/data.d.ts +7 -0
  121. package/lib/typescript/src/data.d.ts.map +1 -0
  122. package/lib/typescript/src/index.d.ts +12 -0
  123. package/lib/typescript/src/index.d.ts.map +1 -0
  124. package/lib/typescript/src/scoket.d.ts +100 -0
  125. package/lib/typescript/src/scoket.d.ts.map +1 -0
  126. package/lib/typescript/src/service.d.ts +9 -0
  127. package/lib/typescript/src/service.d.ts.map +1 -0
  128. package/lib/typescript/src/types.d.ts +22 -0
  129. package/lib/typescript/src/types.d.ts.map +1 -0
  130. package/package.json +178 -0
  131. package/react-native-altibbi.podspec +46 -0
  132. package/src/connection.ts +255 -0
  133. package/src/data.ts +21 -0
  134. package/src/index.tsx +80 -0
  135. package/src/scoket.ts +365 -0
  136. package/src/service.ts +20 -0
  137. package/src/types.ts +22 -0
  138. package/src/video/OT.js +65 -0
  139. package/src/video/OTError.js +14 -0
  140. package/src/video/OTPublisher.js +193 -0
  141. package/src/video/OTSession.js +168 -0
  142. package/src/video/OTSubscriber.js +148 -0
  143. package/src/video/contexts/OTContext.js +5 -0
  144. package/src/video/helpers/OTHelper.js +91 -0
  145. package/src/video/helpers/OTPublisherHelper.js +122 -0
  146. package/src/video/helpers/OTSessionHelper.js +233 -0
  147. package/src/video/helpers/OTSubscriberHelper.js +125 -0
  148. package/src/video/index.js +13 -0
  149. package/src/video/views/OTPublisherView.js +19 -0
  150. package/src/video/views/OTSubscriberView.js +18 -0
@@ -0,0 +1,1281 @@
1
+ package com.altibbi;
2
+
3
+
4
+
5
+ import android.util.Log;
6
+ import android.view.View;
7
+ import android.widget.FrameLayout;
8
+
9
+ import androidx.annotation.Nullable;
10
+
11
+ import com.facebook.react.bridge.Arguments;
12
+ import com.facebook.react.bridge.Callback;
13
+ import com.facebook.react.bridge.LifecycleEventListener;
14
+ import com.facebook.react.bridge.Promise;
15
+ import com.facebook.react.bridge.ReactApplicationContext;
16
+ import com.facebook.react.bridge.ReactContext;
17
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
18
+ import com.facebook.react.bridge.ReactMethod;
19
+ import com.facebook.react.bridge.ReadableArray;
20
+ import com.facebook.react.bridge.ReadableMap;
21
+ import com.facebook.react.bridge.UiThreadUtil;
22
+ import com.facebook.react.bridge.WritableArray;
23
+ import com.facebook.react.bridge.WritableMap;
24
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
25
+ import com.opentok.android.AudioDeviceManager;
26
+ import com.opentok.android.Connection;
27
+ import com.opentok.android.MediaUtils;
28
+ import com.opentok.android.MuteForcedInfo;
29
+ import com.opentok.android.OpentokError;
30
+ import com.opentok.android.Publisher;
31
+ import com.opentok.android.PublisherKit;
32
+ import com.opentok.android.PublisherKit.VideoTransformer;
33
+ import com.opentok.android.Session;
34
+ import com.opentok.android.Session.Builder.IceServer;
35
+ import com.opentok.android.Session.Builder.IncludeServers;
36
+ import com.opentok.android.Session.Builder.TransportPolicy;
37
+ import com.opentok.android.Stream;
38
+ import com.opentok.android.Subscriber;
39
+ import com.opentok.android.SubscriberKit;
40
+ import com.opentok.android.VideoUtils;
41
+ import com.altibbi.utils.EventUtils;
42
+ import com.altibbi.utils.Utils;
43
+
44
+ import java.util.ArrayList;
45
+ import java.util.List;
46
+ import java.util.concurrent.ConcurrentHashMap;
47
+
48
+ public class OTSessionManager extends ReactContextBaseJavaModule
49
+ implements Session.SessionListener,
50
+ PublisherKit.PublisherListener,
51
+ PublisherKit.AudioLevelListener,
52
+ PublisherKit.PublisherRtcStatsReportListener,
53
+ PublisherKit.AudioStatsListener,
54
+ PublisherKit.MuteListener,
55
+ PublisherKit.VideoStatsListener,
56
+ SubscriberKit.SubscriberListener,
57
+ Session.SignalListener,
58
+ Session.ConnectionListener,
59
+ Session.ReconnectionListener,
60
+ Session.ArchiveListener,
61
+ Session.MuteListener,
62
+ Session.StreamPropertiesListener,
63
+ Session.StreamCaptionsPropertiesListener,
64
+ SubscriberKit.AudioLevelListener,
65
+ SubscriberKit.CaptionsListener,
66
+ SubscriberKit.SubscriberRtcStatsReportListener,
67
+ SubscriberKit.AudioStatsListener,
68
+ SubscriberKit.VideoStatsListener,
69
+ SubscriberKit.VideoListener,
70
+ SubscriberKit.StreamListener,
71
+ LifecycleEventListener
72
+ {
73
+
74
+ private ConcurrentHashMap<String, Integer> connectionStatusMap = new ConcurrentHashMap<>();
75
+ private ArrayList<String> jsEvents = new ArrayList<String>();
76
+ private ArrayList<String> componentEvents = new ArrayList<String>();
77
+ private static final String TAG = "OTRN";
78
+ private final String sessionPreface = "session:";
79
+ private final String publisherPreface = "publisher:";
80
+ private final String subscriberPreface = "subscriber:";
81
+ private Boolean logLevel = false;
82
+ public OTRN sharedState;
83
+
84
+ public OTSessionManager(ReactApplicationContext reactContext) {
85
+
86
+ super(reactContext);
87
+ sharedState = OTRN.getSharedState();
88
+ reactContext.addLifecycleEventListener(this);
89
+ }
90
+
91
+ @ReactMethod
92
+ public void initSession(String apiKey, String sessionId, ReadableMap sessionOptions) {
93
+
94
+ final boolean useTextureViews = sessionOptions.getBoolean("useTextureViews");
95
+ final boolean connectionEventsSuppressed = sessionOptions.getBoolean("connectionEventsSuppressed");
96
+ final boolean ipWhitelist = sessionOptions.getBoolean("ipWhitelist");
97
+ final boolean enableStereoOutput = sessionOptions.getBoolean("enableStereoOutput");
98
+ if (enableStereoOutput) {
99
+ OTCustomAudioDriver otCustomAudioDriver = new OTCustomAudioDriver(this.getReactApplicationContext());
100
+ AudioDeviceManager.setAudioDevice(otCustomAudioDriver);
101
+ }
102
+ final List<IceServer> iceServersList = Utils.sanitizeIceServer(sessionOptions.getArray("customServers"));
103
+ final IncludeServers includeServers = Utils.sanitizeIncludeServer(sessionOptions.getString("includeServers"));
104
+ final TransportPolicy transportPolicy = Utils.sanitizeTransportPolicy(sessionOptions.getString("transportPolicy"));
105
+ final String proxyUrl = sessionOptions.getString("proxyUrl");
106
+ String androidOnTop = sessionOptions.getString("androidOnTop");
107
+ String androidZOrder = sessionOptions.getString("androidZOrder");
108
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
109
+ ConcurrentHashMap<String, String> mAndroidOnTopMap = sharedState.getAndroidOnTopMap();
110
+ ConcurrentHashMap<String, String> mAndroidZOrderMap = sharedState.getAndroidZOrderMap();
111
+
112
+
113
+ Session mSession = new Session.Builder(this.getReactApplicationContext(), apiKey, sessionId)
114
+ .sessionOptions(new Session.SessionOptions() {
115
+ @Override
116
+ public boolean useTextureViews() {
117
+ return useTextureViews;
118
+ }
119
+ })
120
+ .connectionEventsSuppressed(connectionEventsSuppressed)
121
+ .setCustomIceServers(iceServersList, includeServers)
122
+ .setIceRouting(transportPolicy)
123
+ .setIpWhitelist(ipWhitelist)
124
+ .setProxyUrl(proxyUrl)
125
+ .build();
126
+ mSession.setSessionListener(this);
127
+ mSession.setSignalListener(this);
128
+ mSession.setConnectionListener(this);
129
+ mSession.setReconnectionListener(this);
130
+ mSession.setArchiveListener(this);
131
+ mSession.setStreamPropertiesListener(this);
132
+ mSession.setMuteListener(this);
133
+ mSessions.put(sessionId, mSession);
134
+ mAndroidOnTopMap.put(sessionId, androidOnTop);
135
+ mAndroidZOrderMap.put(sessionId, androidZOrder);
136
+ }
137
+
138
+ @ReactMethod
139
+ public void connect(String sessionId, String token, Callback callback) {
140
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
141
+ ConcurrentHashMap<String, Callback> mSessionConnectCallbacks = sharedState.getSessionConnectCallbacks();
142
+ mSessionConnectCallbacks.put(sessionId, callback);
143
+ Session mSession = mSessions.get(sessionId);
144
+ if (mSession != null) {
145
+ mSession.connect(token);
146
+ } else {
147
+ WritableMap errorInfo = EventUtils.createError("Error connecting to session. Could not find native session instance");
148
+ callback.invoke(errorInfo);
149
+ }
150
+ }
151
+
152
+ @ReactMethod
153
+ public void initPublisher(String publisherId, ReadableMap properties, Callback callback) {
154
+
155
+ String name = properties.getString("name");
156
+ Boolean videoTrack = properties.getBoolean("videoTrack");
157
+ Boolean audioTrack = properties.getBoolean("audioTrack");
158
+ String cameraPosition = properties.getString("cameraPosition");
159
+ Boolean audioFallbackEnabled = properties.getBoolean("audioFallbackEnabled");
160
+ int audioBitrate = properties.getInt("audioBitrate");
161
+ Boolean enableDtx = properties.getBoolean("enableDtx");
162
+ String frameRate = "FPS_" + properties.getInt("frameRate");
163
+ String resolution = properties.getString("resolution");
164
+ Boolean publishAudio = properties.getBoolean("publishAudio");
165
+ Boolean publishVideo = properties.getBoolean("publishVideo");
166
+ Boolean publishCaptions = properties.getBoolean("publishCaptions");
167
+ String videoSource = properties.getString("videoSource");
168
+ Boolean scalableScreenshare = properties.getBoolean("scalableScreenshare");
169
+ Publisher mPublisher = null;
170
+ if (videoSource.equals("screen")) {
171
+ View view = getCurrentActivity().getWindow().getDecorView().getRootView();
172
+ OTScreenCapturer capturer = new OTScreenCapturer(view);
173
+ mPublisher = new Publisher.Builder(this.getReactApplicationContext())
174
+ .audioTrack(audioTrack)
175
+ .videoTrack(videoTrack)
176
+ .name(name)
177
+ .audioBitrate(audioBitrate)
178
+ .enableOpusDtx(enableDtx)
179
+ .resolution(Publisher.CameraCaptureResolution.valueOf(resolution))
180
+ .frameRate(Publisher.CameraCaptureFrameRate.valueOf(frameRate))
181
+ .capturer(capturer)
182
+ .scalableScreenshare(scalableScreenshare)
183
+ .build();
184
+ mPublisher.setPublisherVideoType(PublisherKit.PublisherKitVideoType.PublisherKitVideoTypeScreen);
185
+ } else {
186
+ mPublisher = new Publisher.Builder(this.getReactApplicationContext())
187
+ .audioTrack(audioTrack)
188
+ .videoTrack(videoTrack)
189
+ .name(name)
190
+ .audioBitrate(audioBitrate)
191
+ .resolution(Publisher.CameraCaptureResolution.valueOf(resolution))
192
+ .frameRate(Publisher.CameraCaptureFrameRate.valueOf(frameRate))
193
+ .build();
194
+ if (cameraPosition.equals("back")) {
195
+ mPublisher.cycleCamera();
196
+ }
197
+ if (mPublisher.getCapturer() != null) {
198
+ mPublisher.getCapturer().setVideoContentHint(Utils.convertVideoContentHint(properties.getString("videoContentHint")));
199
+ }
200
+ }
201
+ mPublisher.setPublisherListener(this);
202
+ mPublisher.setAudioLevelListener(this);
203
+ mPublisher.setRtcStatsReportListener(this);
204
+ mPublisher.setAudioFallbackEnabled(audioFallbackEnabled);
205
+ mPublisher.setPublishVideo(publishVideo);
206
+ mPublisher.setPublishAudio(publishAudio);
207
+ mPublisher.setPublishCaptions(publishCaptions);
208
+ mPublisher.setAudioStatsListener(this);
209
+ mPublisher.setVideoStatsListener(this);
210
+ mPublisher.setMuteListener(this);
211
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
212
+ mPublishers.put(publisherId, mPublisher);
213
+ callback.invoke();
214
+ }
215
+
216
+ @ReactMethod
217
+ public void publish(String sessionId, String publisherId, Callback callback) {
218
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
219
+ Session mSession = mSessions.get(sessionId);
220
+ if (mSession != null) {
221
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
222
+ Publisher mPublisher = mPublishers.get(publisherId);
223
+ if (mPublisher != null) {
224
+ mSession.publish(mPublisher);
225
+ callback.invoke();
226
+ } else {
227
+ WritableMap errorInfo = EventUtils.createError("Error publishing. Could not find native publisher instance.");
228
+ callback.invoke(errorInfo);
229
+ }
230
+ } else {
231
+ WritableMap errorInfo = EventUtils.createError("Error publishing. Could not find native session instance.");
232
+ callback.invoke(errorInfo);
233
+ }
234
+ }
235
+
236
+ @ReactMethod
237
+ public void subscribeToStream(String streamId, String sessionId, ReadableMap properties, Callback callback) {
238
+
239
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
240
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
241
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
242
+ Stream stream = mSubscriberStreams.get(streamId);
243
+ Session mSession = mSessions.get(sessionId);
244
+ Subscriber mSubscriber = new Subscriber.Builder(getReactApplicationContext(), stream).build();
245
+ mSubscriber.setSubscriberListener(this);
246
+ mSubscriber.setAudioLevelListener(this);
247
+ mSubscriber.setAudioStatsListener(this);
248
+ mSubscriber.setVideoStatsListener(this);
249
+ mSubscriber.setRtcStatsReportListener(this);
250
+ mSubscriber.setVideoListener(this);
251
+ mSubscriber.setStreamListener(this);
252
+ mSubscriber.setCaptionsListener(this);
253
+ mSubscriber.setSubscribeToAudio(properties.getBoolean("subscribeToAudio"));
254
+ mSubscriber.setSubscribeToVideo(properties.getBoolean("subscribeToVideo"));
255
+ mSubscriber.setSubscribeToCaptions(properties.getBoolean("subscribeToCaptions"));
256
+ if (properties.hasKey("preferredFrameRate")) {
257
+ mSubscriber.setPreferredFrameRate((float) properties.getDouble("preferredFrameRate"));
258
+ }
259
+ if (properties.hasKey("preferredResolution")
260
+ && properties.getMap("preferredResolution").hasKey("width")
261
+ && properties.getMap("preferredResolution").hasKey("height")) {
262
+ ReadableMap preferredResolution = properties.getMap("preferredResolution");
263
+ VideoUtils.Size resolution = new VideoUtils.Size(
264
+ preferredResolution.getInt("width"),
265
+ preferredResolution.getInt("height"));
266
+ mSubscriber.setPreferredResolution(resolution);
267
+ }
268
+ if (properties.hasKey("audioVolume")) {
269
+ mSubscriber.setAudioVolume((float) properties.getDouble("audioVolume"));
270
+ }
271
+ mSubscribers.put(streamId, mSubscriber);
272
+ if (mSession != null) {
273
+ mSession.subscribe(mSubscriber);
274
+ callback.invoke(null, streamId);
275
+ } else {
276
+ WritableMap errorInfo = EventUtils.createError("Error subscribing. The native session instance could not be found.");
277
+ callback.invoke(errorInfo);
278
+ }
279
+ }
280
+
281
+ @ReactMethod
282
+ public void removeSubscriber(final String streamId, final Callback callback) {
283
+
284
+ UiThreadUtil.runOnUiThread(new Runnable() {
285
+ @Override
286
+ public void run() {
287
+
288
+ String mStreamId = streamId;
289
+ Callback mCallback = callback;
290
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
291
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
292
+ ConcurrentHashMap<String, FrameLayout> mSubscriberViewContainers = sharedState.getSubscriberViewContainers();
293
+ Subscriber mSubscriber = mSubscribers.get(mStreamId);
294
+ FrameLayout mSubscriberViewContainer = mSubscriberViewContainers.get(mStreamId);
295
+ if (mSubscriberViewContainer != null) {
296
+ mSubscriberViewContainer.removeAllViews();
297
+ }
298
+ mSubscriberViewContainers.remove(mStreamId);
299
+ mSubscribers.remove(mStreamId);
300
+ mSubscriberStreams.remove(mStreamId);
301
+ mCallback.invoke();
302
+
303
+ }
304
+ });
305
+ }
306
+
307
+ @ReactMethod
308
+ public void disconnectSession(String sessionId, Callback callback) {
309
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
310
+ ConcurrentHashMap<String, Callback> mSessionDisconnectCallbacks = sharedState.getSessionDisconnectCallbacks();
311
+ Session mSession = mSessions.get(sessionId);
312
+ mSessionDisconnectCallbacks.put(sessionId, callback);
313
+ if (mSession != null) {
314
+ mSession.disconnect();
315
+ }
316
+ }
317
+
318
+ @ReactMethod
319
+ public void forceMuteAll(String sessionId, ReadableArray excludedStreamIds, Promise promise) {
320
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
321
+ Session mSession = mSessions.get(sessionId);
322
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
323
+ ArrayList<Stream> mExcludedStreams = new ArrayList<Stream>();
324
+ if (mSession == null) {
325
+ promise.reject("Session not found.");
326
+ return;
327
+ }
328
+ for (int i = 0; i < excludedStreamIds.size(); i++) {
329
+ String streamId = excludedStreamIds.getString(i);
330
+ Stream mStream = streams.get(streamId);
331
+ if (mStream == null) {
332
+ promise.reject("Stream not found.");
333
+ return;
334
+ }
335
+ mExcludedStreams.add(mStream);
336
+ }
337
+ mSession.forceMuteAll(mExcludedStreams);
338
+ promise.resolve(null);
339
+ }
340
+
341
+ @ReactMethod
342
+ public void forceMuteStream(String sessionId, String streamId, Promise promise) {
343
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
344
+ Session mSession = mSessions.get(sessionId);
345
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
346
+ if (mSession == null) {
347
+ promise.reject("Session not found.");
348
+ return;
349
+ }
350
+ Stream mStream = streams.get(streamId);
351
+ if (mStream == null) {
352
+ promise.reject("Stream not found.");
353
+ return;
354
+ }
355
+ mSession.forceMuteStream(mStream);
356
+ promise.resolve(null);
357
+ }
358
+
359
+ @ReactMethod
360
+ public void disableForceMute(String sessionId, Promise promise) {
361
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
362
+ Session mSession = mSessions.get(sessionId);
363
+ if (mSession == null) {
364
+ promise.reject("Session not found.");
365
+ return;
366
+ }
367
+ mSession.disableForceMute();
368
+ promise.resolve(true);
369
+ }
370
+
371
+ @ReactMethod
372
+ public void publishAudio(String publisherId, Boolean publishAudio) {
373
+
374
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
375
+ Publisher mPublisher = mPublishers.get(publisherId);
376
+ if (mPublisher != null) {
377
+ mPublisher.setPublishAudio(publishAudio);
378
+ }
379
+ }
380
+
381
+ @ReactMethod
382
+ public void publishCaptions(String publisherId, Boolean publishCaptions) {
383
+
384
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
385
+ Publisher mPublisher = mPublishers.get(publisherId);
386
+ if (mPublisher != null) {
387
+ mPublisher.setPublishCaptions(publishCaptions);
388
+ }
389
+ }
390
+
391
+ @ReactMethod
392
+ public void publishVideo(String publisherId, Boolean publishVideo) {
393
+
394
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
395
+ Publisher mPublisher = mPublishers.get(publisherId);
396
+ if (mPublisher != null) {
397
+ mPublisher.setPublishVideo(publishVideo);
398
+ }
399
+ }
400
+
401
+ @ReactMethod
402
+ public void getRtcStatsReport(String publisherId) {
403
+
404
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
405
+ Publisher mPublisher = mPublishers.get(publisherId);
406
+ if (mPublisher != null) {
407
+ mPublisher.getRtcStatsReport();
408
+ }
409
+ }
410
+
411
+ @ReactMethod
412
+ public void setVideoTransformers(String publisherId, ReadableArray videoTransformers) {
413
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
414
+ Publisher mPublisher = mPublishers.get(publisherId);
415
+ if (mPublisher != null) {
416
+ ArrayList<VideoTransformer> nativeVideoTransformers = Utils.sanitizeVideoTransformerList(mPublisher, videoTransformers);
417
+ mPublisher.setVideoTransformers(nativeVideoTransformers);
418
+ }
419
+ }
420
+
421
+ @ReactMethod
422
+ public void subscribeToAudio(String streamId, Boolean subscribeToAudio) {
423
+
424
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
425
+ Subscriber mSubscriber = mSubscribers.get(streamId);
426
+ if (mSubscriber != null) {
427
+ mSubscriber.setSubscribeToAudio(subscribeToAudio);
428
+ }
429
+ }
430
+
431
+ @ReactMethod
432
+ public void subscribeToVideo(String streamId, Boolean subscribeToVideo) {
433
+
434
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
435
+ Subscriber mSubscriber = mSubscribers.get(streamId);
436
+ if (mSubscriber != null) {
437
+ mSubscriber.setSubscribeToVideo(subscribeToVideo);
438
+ }
439
+ }
440
+
441
+ @ReactMethod
442
+ public void subscribeToCaptions(String streamId, Boolean subscribeToCaptions) {
443
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
444
+ Subscriber mSubscriber = mSubscribers.get(streamId);
445
+ if (mSubscriber != null) {
446
+ mSubscriber.setSubscribeToCaptions(subscribeToCaptions);
447
+ }
448
+ }
449
+
450
+ @ReactMethod
451
+ public void setPreferredResolution(String streamId, ReadableMap resolution) {
452
+
453
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
454
+ Subscriber mSubscriber = mSubscribers.get(streamId);
455
+ if (mSubscriber != null ) {
456
+ if (resolution.hasKey("width")
457
+ && resolution.hasKey("height")) {
458
+ VideoUtils.Size preferredResolution = new VideoUtils.Size(
459
+ resolution.getInt("width"),
460
+ resolution.getInt("height"));
461
+ mSubscriber.setPreferredResolution(preferredResolution);
462
+ } else {
463
+ mSubscriber.setPreferredResolution(SubscriberKit.NO_PREFERRED_RESOLUTION);
464
+ }
465
+ }
466
+ }
467
+
468
+ @ReactMethod
469
+ public void setPreferredFrameRate(String streamId, Float frameRate) {
470
+
471
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
472
+ Subscriber mSubscriber = mSubscribers.get(streamId);
473
+ if (mSubscriber != null) {
474
+ mSubscriber.setPreferredFrameRate(frameRate);
475
+ }
476
+ }
477
+
478
+ @ReactMethod
479
+ public void setAudioVolume(String streamId, Float audioVolume) {
480
+
481
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
482
+ Subscriber mSubscriber = mSubscribers.get(streamId);
483
+ if (mSubscriber != null) {
484
+ mSubscriber.setAudioVolume(audioVolume);
485
+ }
486
+ }
487
+
488
+ @ReactMethod
489
+ public void getSubscriberRtcStatsReport(String streamId) {
490
+
491
+ ConcurrentHashMap<String, Subscriber> mSubscribers = sharedState.getSubscribers();
492
+ Subscriber mSubscriber = mSubscribers.get(streamId);
493
+ if (mSubscriber != null) {
494
+ mSubscriber.getRtcStatsReport();
495
+ }
496
+ }
497
+
498
+ @ReactMethod
499
+ public void getSupportedCodecs(Promise promise) {
500
+
501
+ MediaUtils.SupportedCodecs mSupportedCodecs = MediaUtils.getSupportedCodecs(this.getReactApplicationContext());
502
+ WritableMap supportedCodecsMap = EventUtils.prepareMediaCodecsMap(mSupportedCodecs);
503
+ promise.resolve(supportedCodecsMap);
504
+ }
505
+
506
+ @ReactMethod
507
+ public void changeCameraPosition(String publisherId, String cameraPosition) {
508
+
509
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
510
+ Publisher mPublisher = mPublishers.get(publisherId);
511
+ if (mPublisher != null) {
512
+ mPublisher.cycleCamera();
513
+ }
514
+ }
515
+
516
+ @ReactMethod
517
+ public void changeVideoContentHint(String publisherId, String videoContentHint) {
518
+
519
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
520
+ Publisher mPublisher = mPublishers.get(publisherId);
521
+ if (mPublisher != null && mPublisher.getCapturer() != null) {
522
+ mPublisher.getCapturer().setVideoContentHint(Utils.convertVideoContentHint(videoContentHint));
523
+ }
524
+ }
525
+
526
+ @ReactMethod
527
+ public void setNativeEvents(ReadableArray events) {
528
+
529
+ for (int i = 0; i < events.size(); i++) {
530
+ jsEvents.add(events.getString(i));
531
+ }
532
+ }
533
+
534
+ @ReactMethod
535
+ public void removeNativeEvents(ReadableArray events) {
536
+
537
+ for (int i = 0; i < events.size(); i++) {
538
+ jsEvents.remove(events.getString(i));
539
+ }
540
+ }
541
+
542
+ @ReactMethod
543
+ public void setJSComponentEvents(ReadableArray events) {
544
+
545
+ for (int i = 0; i < events.size(); i++) {
546
+ componentEvents.add(events.getString(i));
547
+ }
548
+ }
549
+
550
+ @ReactMethod
551
+ public void removeJSComponentEvents(ReadableArray events) {
552
+
553
+ for (int i = 0; i < events.size(); i++) {
554
+ componentEvents.remove(events.getString(i));
555
+ }
556
+ }
557
+
558
+ // Required for rn built in EventEmitter Calls.
559
+ @ReactMethod
560
+ public void addListener(String eventName) {
561
+
562
+ }
563
+
564
+ @ReactMethod
565
+ public void removeListeners(Integer count) {
566
+
567
+ }
568
+
569
+
570
+ @ReactMethod
571
+ public void sendSignal(String sessionId, ReadableMap signal, Callback callback) {
572
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
573
+ Session mSession = mSessions.get(sessionId);
574
+ ConcurrentHashMap<String, Connection> mConnections = sharedState.getConnections();
575
+ String connectionId = signal.getString("to");
576
+ Connection mConnection = null;
577
+ if (connectionId != null) {
578
+ mConnection = mConnections.get(connectionId);
579
+ }
580
+ if (mConnection != null && mSession != null) {
581
+ mSession.sendSignal(signal.getString("type"), signal.getString("data"), mConnection);
582
+ callback.invoke();
583
+ } else if (mSession != null) {
584
+ mSession.sendSignal(signal.getString("type"), signal.getString("data"));
585
+ callback.invoke();
586
+ } else {
587
+ WritableMap errorInfo = EventUtils.createError("There was an error sending the signal. The native session instance could not be found.");
588
+ callback.invoke(errorInfo);
589
+ }
590
+
591
+ }
592
+
593
+ @ReactMethod
594
+ public void destroyPublisher(final String publisherId, final Callback callback) {
595
+
596
+ UiThreadUtil.runOnUiThread(new Runnable() {
597
+ @Override
598
+ public void run() {
599
+
600
+ ConcurrentHashMap<String, Callback> mPublisherDestroyedCallbacks = sharedState.getPublisherDestroyedCallbacks();
601
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
602
+ ConcurrentHashMap<String, FrameLayout> mPublisherViewContainers = sharedState.getPublisherViewContainers();
603
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
604
+ FrameLayout mPublisherViewContainer = mPublisherViewContainers.get(publisherId);
605
+ Publisher mPublisher = mPublishers.get(publisherId);
606
+ Session mSession = null;
607
+ mPublisherDestroyedCallbacks.put(publisherId, callback);
608
+ if (mPublisher != null && mPublisher.getSession() != null && mPublisher.getSession().getSessionId() != null) {
609
+ mSession = mSessions.get(mPublisher.getSession().getSessionId());
610
+ }
611
+
612
+ if (mPublisherViewContainer != null) {
613
+ mPublisherViewContainer.removeAllViews();
614
+ }
615
+ mPublisherViewContainers.remove(publisherId);
616
+ if (mSession != null && mPublisher != null) {
617
+ mSession.unpublish(mPublisher);
618
+ }
619
+ if (mPublisher != null) {
620
+ mPublisher.getCapturer().stopCapture();
621
+ }
622
+ mPublishers.remove(publisherId);
623
+ }
624
+ });
625
+ }
626
+
627
+ @ReactMethod
628
+ public void getSessionInfo(String sessionId, Callback callback) {
629
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
630
+ Session mSession = mSessions.get(sessionId);
631
+ WritableMap sessionInfo = null;
632
+ if (mSession != null){
633
+ sessionInfo = EventUtils.prepareJSSessionMap(mSession);
634
+ sessionInfo.putString("sessionId", mSession.getSessionId());
635
+ sessionInfo.putInt("connectionStatus", getConnectionStatus(mSession.getSessionId()));
636
+ }
637
+ callback.invoke(sessionInfo);
638
+ }
639
+
640
+ @ReactMethod
641
+ public void getSessionCapabilities(String sessionId, Callback callback) {
642
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
643
+ Session mSession = mSessions.get(sessionId);
644
+ WritableMap sessionCapabilitiesMap = Arguments.createMap();
645
+ if (mSession != null){
646
+ Session.Capabilities sessionCapabilities = mSession.getCapabilities();
647
+ sessionCapabilitiesMap.putBoolean("canForceMute", sessionCapabilities.canForceMute);
648
+ sessionCapabilitiesMap.putBoolean("canPublish", sessionCapabilities.canPublish);
649
+ // Bug in OT Android SDK. This should always be true, but it is set to false:
650
+ sessionCapabilitiesMap.putBoolean("canSubscribe", true);
651
+ }
652
+ callback.invoke(sessionCapabilitiesMap);
653
+ }
654
+
655
+ @ReactMethod
656
+ public void reportIssue(String sessionId, Callback callback) {
657
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
658
+ Session mSession = mSessions.get(sessionId);
659
+ if (mSession != null){
660
+ callback.invoke(mSession.reportIssue());
661
+ } else {
662
+ callback.invoke(null, "Error connecting to session. Could not find native session instance.");
663
+
664
+ }
665
+ }
666
+
667
+ @ReactMethod
668
+ public void enableLogs(Boolean logLevel) {
669
+ setLogLevel(logLevel);
670
+ }
671
+
672
+ private void setLogLevel(Boolean logLevel) {
673
+ this.logLevel = logLevel;
674
+ }
675
+
676
+ private void sendEventMap(ReactContext reactContext, String eventName, @Nullable WritableMap eventData) {
677
+
678
+ if (Utils.contains(jsEvents, eventName) || Utils.contains(componentEvents, eventName)) {
679
+ reactContext
680
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
681
+ .emit(eventName, eventData);
682
+ }
683
+ }
684
+
685
+ private void sendEventArray(ReactContext reactContext, String eventName, @Nullable WritableArray eventData) {
686
+
687
+ if (Utils.contains(jsEvents, eventName) || Utils.contains(componentEvents, eventName)) {
688
+ reactContext
689
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
690
+ .emit(eventName, eventData);
691
+ }
692
+ }
693
+
694
+ private void sendEventWithString(ReactContext reactContext, String eventName, String eventString) {
695
+
696
+ if (Utils.contains(jsEvents, eventName) || Utils.contains(componentEvents, eventName)) {
697
+ reactContext
698
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
699
+ .emit(eventName, eventString);
700
+ }
701
+ }
702
+
703
+ private Integer getConnectionStatus(String sessionId) {
704
+ Integer connectionStatus = 0;
705
+ if (this.connectionStatusMap.get(sessionId) != null) {
706
+ connectionStatus = this.connectionStatusMap.get(sessionId);
707
+ }
708
+ return connectionStatus;
709
+ }
710
+
711
+ private void setConnectionStatus(String sessionId, Integer connectionStatus) {
712
+ this.connectionStatusMap.put(sessionId, connectionStatus);
713
+ }
714
+
715
+
716
+ private void printLogs(String message) {
717
+ if (this.logLevel) {
718
+ Log.i(TAG, message);
719
+ }
720
+ }
721
+
722
+ @Override
723
+ public String getName() {
724
+
725
+ return this.getClass().getSimpleName();
726
+ }
727
+
728
+ @Override
729
+ public void onError(Session session, OpentokError opentokError) {
730
+
731
+ if (Utils.didConnectionFail(opentokError)) {
732
+ setConnectionStatus(session.getSessionId(), 6);
733
+ }
734
+ WritableMap errorInfo = EventUtils.prepareJSErrorMap(opentokError);
735
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onError", errorInfo);
736
+ printLogs("There was an error");
737
+ }
738
+
739
+ @Override
740
+ public void onDisconnected(Session session) {
741
+ ConcurrentHashMap<String, Session> mSessions = sharedState.getSessions();
742
+ ConcurrentHashMap<String, Callback> mSessionDisconnectCallbacks = sharedState.getSessionDisconnectCallbacks();
743
+ ConcurrentHashMap<String, Callback> mSessionConnectCallbacks = sharedState.getSessionDisconnectCallbacks();
744
+ setConnectionStatus(session.getSessionId(), 0);
745
+ WritableMap sessionInfo = EventUtils.prepareJSSessionMap(session);
746
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onDisconnected", sessionInfo);
747
+ Callback disconnectCallback = mSessionDisconnectCallbacks.get(session.getSessionId());
748
+ if (disconnectCallback != null) {
749
+ disconnectCallback.invoke();
750
+ }
751
+ mSessions.remove(session.getSessionId());
752
+ mSessionConnectCallbacks.remove(session.getSessionId());
753
+ mSessionDisconnectCallbacks.remove(session.getSessionId());
754
+ printLogs("onDisconnected: Disconnected from session: " + session.getSessionId());
755
+ }
756
+
757
+ @Override
758
+ public void onStreamReceived(Session session, Stream stream) {
759
+
760
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
761
+ mSubscriberStreams.put(stream.getStreamId(), stream);
762
+ WritableMap streamInfo = EventUtils.prepareJSStreamMap(stream, session);
763
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamReceived", streamInfo);
764
+ printLogs("onStreamReceived: New Stream Received " + stream.getStreamId() + " in session: " + session.getSessionId());
765
+
766
+ }
767
+
768
+ @Override
769
+ public void onConnected(Session session) {
770
+
771
+ setConnectionStatus(session.getSessionId(), 1);
772
+ ConcurrentHashMap<String, Callback> mSessionConnectCallbacks = sharedState.getSessionConnectCallbacks();
773
+ Callback mCallback = mSessionConnectCallbacks.get(session.getSessionId());
774
+ if (mCallback != null) {
775
+ mCallback.invoke();
776
+ }
777
+ WritableMap sessionInfo = EventUtils.prepareJSSessionMap(session);
778
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onConnected", sessionInfo);
779
+ printLogs("onConnected: Connected to session: "+session.getSessionId());
780
+ }
781
+
782
+ @Override
783
+ public void onReconnected(Session session) {
784
+
785
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onReconnected", null);
786
+ printLogs("Reconnected");
787
+ }
788
+
789
+ @Override
790
+ public void onReconnecting(Session session) {
791
+
792
+ setConnectionStatus(session.getSessionId(), 3);
793
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onReconnecting", null);
794
+ printLogs("Reconnecting");
795
+ }
796
+
797
+ @Override
798
+ public void onArchiveStarted(Session session, String id, String name) {
799
+
800
+ WritableMap archiveInfo = Arguments.createMap();
801
+ archiveInfo.putString("archiveId", id);
802
+ archiveInfo.putString("name", name);
803
+ archiveInfo.putString("sessionId", session.getSessionId());
804
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onArchiveStarted", archiveInfo);
805
+ printLogs("Archive Started: " + id);
806
+ }
807
+
808
+ @Override
809
+ public void onArchiveStopped(Session session, String id) {
810
+
811
+ WritableMap archiveInfo = Arguments.createMap();
812
+ archiveInfo.putString("archiveId", id);
813
+ archiveInfo.putString("name", "");
814
+ archiveInfo.putString("sessionId", session.getSessionId());
815
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onArchiveStopped", archiveInfo);
816
+ printLogs("Archive Stopped: " + id);
817
+ }
818
+ @Override
819
+ public void onConnectionCreated(Session session, Connection connection) {
820
+
821
+ ConcurrentHashMap<String, Connection> mConnections = sharedState.getConnections();
822
+ mConnections.put(connection.getConnectionId(), connection);
823
+ WritableMap connectionInfo = EventUtils.prepareJSConnectionMap(connection);
824
+ connectionInfo.putString("sessionId", session.getSessionId());
825
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onConnectionCreated", connectionInfo);
826
+ printLogs("onConnectionCreated: Connection Created: "+connection.getConnectionId());
827
+ }
828
+
829
+ @Override
830
+ public void onConnectionDestroyed(Session session, Connection connection) {
831
+
832
+ ConcurrentHashMap<String, Connection> mConnections = sharedState.getConnections();
833
+ mConnections.remove(connection.getConnectionId());
834
+ WritableMap connectionInfo = EventUtils.prepareJSConnectionMap(connection);
835
+ connectionInfo.putString("sessionId", session.getSessionId());
836
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onConnectionDestroyed", connectionInfo);
837
+ printLogs("onConnectionDestroyed: Connection Destroyed: "+connection.getConnectionId());
838
+ }
839
+ @Override
840
+ public void onStreamDropped(Session session, Stream stream) {
841
+
842
+ WritableMap streamInfo = EventUtils.prepareJSStreamMap(stream, session);
843
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamDropped", streamInfo);
844
+ printLogs("onStreamDropped: Stream Dropped: "+stream.getStreamId() +" in session: "+session.getSessionId());
845
+ }
846
+ @Override
847
+ public void onMuteForced​(Session session, MuteForcedInfo info) {
848
+
849
+ WritableMap muteForcedInfo = Arguments.createMap();
850
+ String sessionId = session.getSessionId();
851
+ muteForcedInfo.putString("sessionId", sessionId);
852
+ Boolean active = info.getActive();
853
+ muteForcedInfo.putBoolean("active", active);
854
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onMuteForced​", muteForcedInfo);
855
+ printLogs("Mute forced -- active: " + active + " in session: " + sessionId);
856
+ }
857
+
858
+ @Override
859
+ public void onStreamCreated(PublisherKit publisherKit, Stream stream) {
860
+
861
+ String publisherId = Utils.getPublisherId(publisherKit);
862
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
863
+ mSubscriberStreams.put(stream.getStreamId(), stream);
864
+ if (publisherId.length() > 0) {
865
+ String event = publisherId + ":" + publisherPreface + "onStreamCreated";;
866
+ WritableMap streamInfo = EventUtils.prepareJSStreamMap(stream, publisherKit.getSession());
867
+ sendEventMap(this.getReactApplicationContext(), event, streamInfo);
868
+ }
869
+ printLogs("onStreamCreated: Publisher Stream Created. Own stream "+stream.getStreamId());
870
+
871
+ }
872
+
873
+ @Override
874
+ public void onStreamDestroyed(PublisherKit publisherKit, Stream stream) {
875
+
876
+ String publisherId = Utils.getPublisherId(publisherKit);
877
+ String event = publisherId + ":" + publisherPreface + "onStreamDestroyed";
878
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
879
+ String mStreamId = stream.getStreamId();
880
+ mSubscriberStreams.remove(mStreamId);
881
+ if (publisherId.length() > 0) {
882
+ WritableMap streamInfo = EventUtils.prepareJSStreamMap(stream, publisherKit.getSession());
883
+ sendEventMap(this.getReactApplicationContext(), event, streamInfo);
884
+ }
885
+ Callback mCallback = sharedState.getPublisherDestroyedCallbacks().get(publisherId);
886
+ if (mCallback != null) {
887
+ mCallback.invoke();
888
+ }
889
+ sharedState.getPublishers().remove(publisherId);
890
+ printLogs("onStreamDestroyed: Publisher Stream Destroyed. Own stream "+stream.getStreamId());
891
+ }
892
+
893
+ @Override
894
+ public void onError(PublisherKit publisherKit, OpentokError opentokError) {
895
+
896
+ String publisherId = Utils.getPublisherId(publisherKit);
897
+ if (publisherId.length() > 0) {
898
+ String event = publisherId + ":" + publisherPreface + "onError";
899
+ WritableMap errorInfo = EventUtils.prepareJSErrorMap(opentokError);
900
+ sendEventMap(this.getReactApplicationContext(), event, errorInfo);
901
+ }
902
+ printLogs("onError: "+opentokError.getErrorDomain() + " : " +
903
+ opentokError.getErrorCode() + " - "+opentokError.getMessage());
904
+ }
905
+
906
+ @Override
907
+ public void onAudioLevelUpdated(PublisherKit publisher, float audioLevel) {
908
+
909
+ String publisherId = Utils.getPublisherId(publisher);
910
+ if (publisherId.length() > 0) {
911
+ String event = publisherId + ":" + publisherPreface + "onAudioLevelUpdated";
912
+ sendEventWithString(this.getReactApplicationContext(), event, String.valueOf(audioLevel));
913
+ }
914
+ }
915
+
916
+ @Override
917
+ public void onRtcStatsReport(PublisherKit publisher, PublisherKit.PublisherRtcStats[] stats) {
918
+
919
+ String publisherId = Utils.getPublisherId(publisher);
920
+ if (publisherId.length() > 0) {
921
+ WritableArray rtcStatsReportArray = EventUtils.preparePublisherRtcStats(stats);
922
+ String event = publisherId + ":" + publisherPreface + "onRtcStatsReport";
923
+ sendEventArray(this.getReactApplicationContext(), event, rtcStatsReportArray);
924
+ }
925
+ }
926
+
927
+ @Override
928
+ public void onAudioStats(PublisherKit publisher, PublisherKit.PublisherAudioStats[] stats) {
929
+
930
+ String publisherId = Utils.getPublisherId(publisher);
931
+ if (publisherId.length() > 0) {
932
+ WritableArray publisherInfo = EventUtils.preparePublisherAudioStats(stats);
933
+ String event = publisherId + ":" + publisherPreface + "onAudioStats";
934
+ sendEventArray(this.getReactApplicationContext(), event, publisherInfo);
935
+ }
936
+ }
937
+
938
+ @Override
939
+ public void onVideoStats(PublisherKit publisher, PublisherKit.PublisherVideoStats[] stats) {
940
+
941
+ String publisherId = Utils.getPublisherId(publisher);
942
+ if (publisherId.length() > 0) {
943
+ WritableArray publisherInfo = EventUtils.preparePublisherVideoStats(stats);
944
+ String event = publisherId + ":" + publisherPreface + "onVideoStats";
945
+ sendEventArray(this.getReactApplicationContext(), event, publisherInfo);
946
+ }
947
+ }
948
+
949
+ @Override
950
+ public void onMuteForced​(PublisherKit publisher) {
951
+
952
+ String publisherId = Utils.getPublisherId(publisher);
953
+ if (publisherId.length() > 0) {
954
+ String event = publisherId + ":" + publisherPreface + "onMuteForced";
955
+ sendEventMap(this.getReactApplicationContext(), event, null);
956
+ }
957
+ }
958
+
959
+ @Override
960
+ public void onConnected(SubscriberKit subscriberKit) {
961
+
962
+ String streamId = Utils.getStreamIdBySubscriber(subscriberKit);
963
+ if (streamId.length() > 0) {
964
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
965
+ Stream mStream = streams.get(streamId);
966
+ WritableMap subscriberInfo = Arguments.createMap();
967
+ if (mStream != null) {
968
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriberKit.getSession()));
969
+ }
970
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onConnected", subscriberInfo);
971
+ }
972
+ printLogs("onConnected: Subscriber connected. Stream: "+subscriberKit.getStream().getStreamId());
973
+ }
974
+
975
+ @Override
976
+ public void onDisconnected(SubscriberKit subscriberKit) {
977
+
978
+ String streamId = Utils.getStreamIdBySubscriber(subscriberKit);
979
+ if (streamId.length() > 0) {
980
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
981
+ Stream mStream = streams.get(streamId);
982
+ WritableMap subscriberInfo = Arguments.createMap();
983
+ if (mStream != null) {
984
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriberKit.getSession()));
985
+ }
986
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onDisconnected", subscriberInfo);
987
+ }
988
+ printLogs("onDisconnected: Subscriber disconnected. Stream: "+subscriberKit.getStream().getStreamId());
989
+ }
990
+
991
+ @Override
992
+ public void onReconnected(SubscriberKit subscriberKit) {
993
+
994
+ String streamId = Utils.getStreamIdBySubscriber(subscriberKit);
995
+ if (streamId.length() > 0) {
996
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
997
+ Stream mStream = streams.get(streamId);
998
+ WritableMap subscriberInfo = Arguments.createMap();
999
+ if (mStream != null) {
1000
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriberKit.getSession()));
1001
+ }
1002
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onReconnected", subscriberInfo);
1003
+ }
1004
+ printLogs("onReconnected: Subscriber reconnected. Stream: "+subscriberKit.getStream().getStreamId());
1005
+ }
1006
+
1007
+ @Override
1008
+ public void onError(SubscriberKit subscriberKit, OpentokError opentokError) {
1009
+
1010
+ String streamId = Utils.getStreamIdBySubscriber(subscriberKit);
1011
+ if (streamId.length() > 0) {
1012
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1013
+ Stream mStream = streams.get(streamId);
1014
+ WritableMap subscriberInfo = Arguments.createMap();
1015
+ if (mStream != null) {
1016
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriberKit.getSession()));
1017
+ }
1018
+ subscriberInfo.putMap("error", EventUtils.prepareJSErrorMap(opentokError));
1019
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onError", subscriberInfo);
1020
+ }
1021
+ printLogs("onError: "+opentokError.getErrorDomain() + " : " +
1022
+ opentokError.getErrorCode() + " - "+opentokError.getMessage());
1023
+
1024
+ }
1025
+
1026
+ @Override
1027
+ public void onRtcStatsReport(SubscriberKit subscriberKit, String stats) {
1028
+
1029
+ String streamId = Utils.getStreamIdBySubscriber(subscriberKit);
1030
+ if (streamId.length() > 0) {
1031
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1032
+ Stream mStream = streams.get(streamId);
1033
+ WritableMap subscriberInfo = Arguments.createMap();
1034
+ if (mStream != null) {
1035
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriberKit.getSession()));
1036
+ }
1037
+ subscriberInfo.putString("jsonArrayOfReports", stats);
1038
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onRtcStatsReport", subscriberInfo);
1039
+ }
1040
+ }
1041
+
1042
+ @Override
1043
+ public void onSignalReceived(Session session, String type, String data, Connection connection) {
1044
+
1045
+ WritableMap signalInfo = Arguments.createMap();
1046
+ signalInfo.putString("type", type);
1047
+ signalInfo.putString("data", data);
1048
+ if(connection != null) {
1049
+ signalInfo.putString("connectionId", connection.getConnectionId());
1050
+ }
1051
+ signalInfo.putString("sessionId", session.getSessionId());
1052
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onSignalReceived", signalInfo);
1053
+ printLogs("onSignalReceived: Data: " + data + " Type: " + type);
1054
+ }
1055
+
1056
+ @Override
1057
+ public void onAudioStats(SubscriberKit subscriber, SubscriberKit.SubscriberAudioStats stats) {
1058
+
1059
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1060
+ if (streamId.length() > 0) {
1061
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1062
+ Stream mStream = streams.get(streamId);
1063
+ WritableMap subscriberInfo = Arguments.createMap();
1064
+ if (mStream != null) {
1065
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1066
+ }
1067
+ subscriberInfo.putMap("audioStats", EventUtils.prepareAudioNetworkStats(stats));
1068
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onAudioStats", subscriberInfo);
1069
+ }
1070
+ }
1071
+
1072
+ @Override
1073
+ public void onVideoStats(SubscriberKit subscriber, SubscriberKit.SubscriberVideoStats stats) {
1074
+
1075
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1076
+ if (streamId.length() > 0) {
1077
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1078
+ Stream mStream = streams.get(streamId);
1079
+ WritableMap subscriberInfo = Arguments.createMap();
1080
+ if (mStream != null) {
1081
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1082
+ }
1083
+ subscriberInfo.putMap("videoStats", EventUtils.prepareVideoNetworkStats(stats));
1084
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onVideoStats", subscriberInfo);
1085
+ }
1086
+ }
1087
+
1088
+ @Override
1089
+ public void onAudioLevelUpdated(SubscriberKit subscriber, float audioLevel) {
1090
+
1091
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1092
+ if (streamId.length() > 0) {
1093
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1094
+ Stream mStream = streams.get(streamId);
1095
+ WritableMap subscriberInfo = Arguments.createMap();
1096
+ if (mStream != null) {
1097
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1098
+ }
1099
+ subscriberInfo.putString("audioLevel", String.valueOf(audioLevel));
1100
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onAudioLevelUpdated", subscriberInfo);
1101
+ }
1102
+ }
1103
+
1104
+ @Override
1105
+ public void onVideoDisabled(SubscriberKit subscriber, String reason) {
1106
+
1107
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1108
+ if (streamId.length() > 0) {
1109
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1110
+ Stream mStream = streams.get(streamId);
1111
+ WritableMap subscriberInfo = Arguments.createMap();
1112
+ if (mStream != null) {
1113
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1114
+ }
1115
+ subscriberInfo.putString("reason", reason);
1116
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onVideoDisabled", subscriberInfo);
1117
+ }
1118
+ printLogs("onVideoDisabled " + reason);
1119
+ }
1120
+
1121
+ @Override
1122
+ public void onVideoEnabled(SubscriberKit subscriber, String reason) {
1123
+
1124
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1125
+ if (streamId.length() > 0) {
1126
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1127
+ Stream mStream = streams.get(streamId);
1128
+ WritableMap subscriberInfo = Arguments.createMap();
1129
+ if (mStream != null) {
1130
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1131
+ }
1132
+ subscriberInfo.putString("reason", reason);
1133
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onVideoEnabled", subscriberInfo);
1134
+ }
1135
+ printLogs("onVideoEnabled " + reason);
1136
+ }
1137
+
1138
+ @Override
1139
+ public void onVideoDisableWarning(SubscriberKit subscriber) {
1140
+
1141
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1142
+ if (streamId.length() > 0) {
1143
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1144
+ Stream mStream = streams.get(streamId);
1145
+ WritableMap subscriberInfo = Arguments.createMap();
1146
+ if (mStream != null) {
1147
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1148
+ }
1149
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onVideoDisableWarning", subscriberInfo);
1150
+ }
1151
+ printLogs("onVideoDisableWarning");
1152
+ }
1153
+
1154
+ @Override
1155
+ public void onVideoDisableWarningLifted(SubscriberKit subscriber) {
1156
+
1157
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1158
+ if (streamId.length() > 0) {
1159
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1160
+ Stream mStream = streams.get(streamId);
1161
+ WritableMap subscriberInfo = Arguments.createMap();
1162
+ if (mStream != null) {
1163
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1164
+ }
1165
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onVideoDisableWarningLifted", subscriberInfo);
1166
+ }
1167
+ printLogs("onVideoDisableWarningLifted");
1168
+ }
1169
+
1170
+ @Override
1171
+ public void onVideoDataReceived(SubscriberKit subscriber) {
1172
+
1173
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1174
+ if (streamId.length() > 0) {
1175
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1176
+ Stream mStream = streams.get(streamId);
1177
+ WritableMap subscriberInfo = Arguments.createMap();
1178
+ if (mStream != null) {
1179
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1180
+ }
1181
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onVideoDataReceived", subscriberInfo);
1182
+ }
1183
+ }
1184
+
1185
+ @Override
1186
+ public void onCaptionText(SubscriberKit subscriber, String text, boolean isFinal) {
1187
+ String streamId = Utils.getStreamIdBySubscriber(subscriber);
1188
+ if (streamId.length() > 0) {
1189
+ ConcurrentHashMap<String, Stream> streams = sharedState.getSubscriberStreams();
1190
+ Stream mStream = streams.get(streamId);
1191
+ WritableMap subscriberInfo = Arguments.createMap();
1192
+ if (mStream != null) {
1193
+ subscriberInfo.putMap("stream", EventUtils.prepareJSStreamMap(mStream, subscriber.getSession()));
1194
+ }
1195
+ subscriberInfo.putString("text", String.valueOf(text));
1196
+ subscriberInfo.putBoolean("isFinal", isFinal);
1197
+ sendEventMap(this.getReactApplicationContext(), subscriberPreface + "onCaptionText", subscriberInfo);
1198
+ }
1199
+ }
1200
+
1201
+ @Override
1202
+ public void onStreamHasAudioChanged(Session session, Stream stream, boolean Audio) {
1203
+
1204
+ WritableMap eventData = EventUtils.prepareStreamPropertyChangedEventData("hasAudio", !Audio, Audio, stream, session);
1205
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamPropertyChanged", eventData);
1206
+ printLogs("onStreamHasAudioChanged");
1207
+ }
1208
+
1209
+ @Override
1210
+ public void onStreamHasCaptionsChanged(Session session, Stream stream, boolean hasCaptions) {
1211
+ if (stream != null) {
1212
+ WritableMap eventData = EventUtils.prepareStreamPropertyChangedEventData("hasCaptions", !hasCaptions, hasCaptions, stream, session);
1213
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamPropertyChanged", eventData);
1214
+ printLogs("onStreamHasCaptionsChanged");
1215
+ }
1216
+ }
1217
+
1218
+ @Override
1219
+ public void onStreamHasVideoChanged(Session session, Stream stream, boolean Video) {
1220
+
1221
+ WritableMap eventData = EventUtils.prepareStreamPropertyChangedEventData("hasVideo", !Video, Video, stream, session);
1222
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamPropertyChanged", eventData);
1223
+ printLogs("onStreamHasVideoChanged");
1224
+ }
1225
+
1226
+ @Override
1227
+ public void onStreamVideoDimensionsChanged(Session session, Stream stream, int width, int height) {
1228
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
1229
+ Stream mStream = mSubscriberStreams.get(stream.getStreamId());
1230
+ WritableMap oldVideoDimensions = Arguments.createMap();
1231
+ if ( mStream != null ){
1232
+ oldVideoDimensions.putInt("height", mStream.getVideoHeight());
1233
+ oldVideoDimensions.putInt("width", mStream.getVideoWidth());
1234
+ }
1235
+ WritableMap newVideoDimensions = Arguments.createMap();
1236
+ newVideoDimensions.putInt("height", height);
1237
+ newVideoDimensions.putInt("width", width);
1238
+ WritableMap eventData = EventUtils.prepareStreamPropertyChangedEventData("videoDimensions", oldVideoDimensions, newVideoDimensions, stream, session);
1239
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamPropertyChanged", eventData);
1240
+ printLogs("onStreamVideoDimensionsChanged");
1241
+
1242
+ }
1243
+
1244
+ @Override
1245
+ public void onStreamVideoTypeChanged(Session session, Stream stream, Stream.StreamVideoType videoType) {
1246
+
1247
+ ConcurrentHashMap<String, Stream> mSubscriberStreams = sharedState.getSubscriberStreams();
1248
+ String oldVideoType = stream.getStreamVideoType().toString();
1249
+ WritableMap eventData = EventUtils.prepareStreamPropertyChangedEventData("videoType", oldVideoType, videoType.toString(), stream, session);
1250
+ sendEventMap(this.getReactApplicationContext(), session.getSessionId() + ":" + sessionPreface + "onStreamPropertyChanged", eventData);
1251
+ printLogs("onStreamVideoTypeChanged");
1252
+ }
1253
+ @Override
1254
+ public void onHostResume() {
1255
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
1256
+
1257
+ for (String key: mPublishers.keySet()) {
1258
+ Publisher publisher = mPublishers.get(key);
1259
+
1260
+ if (publisher != null) {
1261
+ publisher.onResume();
1262
+ }
1263
+ }
1264
+ }
1265
+
1266
+ @Override
1267
+ public void onHostPause() {
1268
+ ConcurrentHashMap<String, Publisher> mPublishers = sharedState.getPublishers();
1269
+
1270
+ for (String key: mPublishers.keySet()) {
1271
+ Publisher publisher = mPublishers.get(key);
1272
+
1273
+ if (publisher != null) {
1274
+ publisher.onPause();
1275
+ }
1276
+ }
1277
+ }
1278
+ @Override
1279
+ public void onHostDestroy() {}
1280
+
1281
+ }