浏览代码

feat(mobile) adds ability to retrieve participantsInfo array

j8
tmoldovan8x8 4 年前
父节点
当前提交
d2568b874b
没有帐户链接到提交者的电子邮件

+ 1
- 0
android/sdk/build.gradle 查看文件

@@ -47,6 +47,7 @@ dependencies {
47 47
     implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
48 48
     implementation 'com.jakewharton.timber:timber:4.7.1'
49 49
     implementation 'com.squareup.duktape:duktape-android:1.3.0'
50
+    implementation 'com.google.code.gson:gson:2.8.6'
50 51
 
51 52
     if (rootProject.ext.libreBuild) {
52 53
         implementation(project(':react-native-device-info')) {

+ 2
- 1
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastAction.java 查看文件

@@ -62,7 +62,8 @@ public class BroadcastAction {
62 62
         SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
63 63
         HANG_UP("org.jitsi.meet.HANG_UP"),
64 64
         SEND_ENDPOINT_TEXT_MESSAGE("org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE"),
65
-        TOGGLE_SCREEN_SHARE("org.jitsi.meet.TOGGLE_SCREEN_SHARE");
65
+        TOGGLE_SCREEN_SHARE("org.jitsi.meet.TOGGLE_SCREEN_SHARE"),
66
+        RETRIEVE_PARTICIPANTS_INFO("org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO");
66 67
 
67 68
         private final String action;
68 69
 

+ 6
- 2
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastEvent.java 查看文件

@@ -82,7 +82,8 @@ public class BroadcastEvent {
82 82
         PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"),
83 83
         PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT"),
84 84
         ENDPOINT_TEXT_MESSAGE_RECEIVED("org.jitsi.meet.ENDPOINT_TEXT_MESSAGE_RECEIVED"),
85
-        SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED");
85
+        SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED"),
86
+        PARTICIPANTS_INFO_RETRIEVED("org.jitsi.meet.PARTICIPANTS_INFO_RETRIEVED");
86 87
 
87 88
         private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
88 89
         private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@@ -91,7 +92,8 @@ public class BroadcastEvent {
91 92
         private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED";
92 93
         private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT";
93 94
         private static final String ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME = "ENDPOINT_TEXT_MESSAGE_RECEIVED";
94
-        private static final String SCREEN_SHARE_TOGGLED_NAME= "SCREEN_SHARE_TOGGLED";
95
+        private static final String SCREEN_SHARE_TOGGLED_NAME = "SCREEN_SHARE_TOGGLED";
96
+        private static final String PARTICIPANTS_INFO_RETRIEVED_NAME = "PARTICIPANTS_INFO_RETRIEVED";
95 97
 
96 98
         private final String action;
97 99
 
@@ -130,6 +132,8 @@ public class BroadcastEvent {
130 132
                     return ENDPOINT_TEXT_MESSAGE_RECEIVED;
131 133
                 case SCREEN_SHARE_TOGGLED_NAME:
132 134
                     return SCREEN_SHARE_TOGGLED;
135
+                case PARTICIPANTS_INFO_RETRIEVED_NAME:
136
+                    return PARTICIPANTS_INFO_RETRIEVED;
133 137
             }
134 138
 
135 139
             return null;

+ 3
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ExternalAPIModule.java 查看文件

@@ -53,6 +53,8 @@ class ExternalAPIModule
53 53
 
54 54
         broadcastEmitter = new BroadcastEmitter(reactContext);
55 55
         broadcastReceiver = new BroadcastReceiver(reactContext);
56
+
57
+        ParticipantsService.init(reactContext);
56 58
     }
57 59
 
58 60
     /**
@@ -79,6 +81,7 @@ class ExternalAPIModule
79 81
         constants.put("HANG_UP", BroadcastAction.Type.HANG_UP.getAction());
80 82
         constants.put("SEND_ENDPOINT_TEXT_MESSAGE", BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
81 83
         constants.put("TOGGLE_SCREEN_SHARE", BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
84
+        constants.put("RETRIEVE_PARTICIPANTS_INFO", BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction());
82 85
 
83 86
         return constants;
84 87
     }

+ 27
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ParticipantInfo.java 查看文件

@@ -0,0 +1,27 @@
1
+package org.jitsi.meet.sdk;
2
+
3
+import com.google.gson.annotations.SerializedName;
4
+
5
+public class ParticipantInfo {
6
+
7
+    @SerializedName("participantId")
8
+    public String id;
9
+
10
+    @SerializedName("displayName")
11
+    public String displayName;
12
+
13
+    @SerializedName("avatarUrl")
14
+    public String avatarUrl;
15
+
16
+    @SerializedName("email")
17
+    public String email;
18
+
19
+    @SerializedName("name")
20
+    public String name;
21
+
22
+    @SerializedName("isLocal")
23
+    public boolean isLocal;
24
+
25
+    @SerializedName("role")
26
+    public String role;
27
+}

+ 90
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ParticipantsService.java 查看文件

@@ -0,0 +1,90 @@
1
+package org.jitsi.meet.sdk;
2
+
3
+import android.content.Context;
4
+import android.content.Intent;
5
+import android.content.IntentFilter;
6
+
7
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
8
+
9
+import com.facebook.react.bridge.Arguments;
10
+import com.facebook.react.bridge.WritableMap;
11
+import com.google.gson.Gson;
12
+import com.google.gson.reflect.TypeToken;
13
+
14
+import org.jitsi.meet.sdk.log.JitsiMeetLogger;
15
+
16
+import java.lang.ref.WeakReference;
17
+import java.util.ArrayList;
18
+import java.util.HashMap;
19
+import java.util.List;
20
+import java.util.Map;
21
+import java.util.UUID;
22
+
23
+import javax.annotation.Nullable;
24
+
25
+public class ParticipantsService extends android.content.BroadcastReceiver {
26
+
27
+    private static final String TAG = ParticipantsService.class.getSimpleName();
28
+    private static final String REQUEST_ID = "requestId";
29
+
30
+    private final Map<String, WeakReference<ParticipantsInfoCallback>> participantsInfoCallbackMap = new HashMap<>();
31
+
32
+    private static ParticipantsService instance;
33
+
34
+    @Nullable
35
+    public static ParticipantsService getInstance() {
36
+        return instance;
37
+    }
38
+
39
+    private ParticipantsService(Context context) {
40
+        LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
41
+
42
+        IntentFilter intentFilter = new IntentFilter();
43
+        intentFilter.addAction(BroadcastEvent.Type.PARTICIPANTS_INFO_RETRIEVED.getAction());
44
+        localBroadcastManager.registerReceiver(this, intentFilter);
45
+    }
46
+
47
+    static void init(Context context) {
48
+        instance = new ParticipantsService(context);
49
+    }
50
+
51
+    public void retrieveParticipantsInfo(ParticipantsInfoCallback participantsInfoCallback) {
52
+        String callbackKey = UUID.randomUUID().toString();
53
+        this.participantsInfoCallbackMap.put(callbackKey, new WeakReference<>(participantsInfoCallback));
54
+
55
+        String actionName = BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction();
56
+        WritableMap data = Arguments.createMap();
57
+        data.putString(REQUEST_ID, callbackKey);
58
+        ReactInstanceManagerHolder.emitEvent(actionName, data);
59
+    }
60
+
61
+    @Override
62
+    public void onReceive(Context context, Intent intent) {
63
+        BroadcastEvent event = new BroadcastEvent(intent);
64
+
65
+        switch (event.getType()) {
66
+            case PARTICIPANTS_INFO_RETRIEVED:
67
+                try {
68
+                    List<ParticipantInfo> participantInfoList = new Gson().fromJson(
69
+                        event.getData().get("participantsInfo").toString(),
70
+                        new TypeToken<ArrayList<ParticipantInfo>>() {
71
+                        }.getType());
72
+
73
+                    ParticipantsInfoCallback participantsInfoCallback = this.participantsInfoCallbackMap.get(event.getData().get(REQUEST_ID).toString()).get();
74
+
75
+                    if (participantsInfoCallback != null) {
76
+                        participantsInfoCallback.onReceived(participantInfoList);
77
+                        this.participantsInfoCallbackMap.remove(participantsInfoCallback);
78
+                    }
79
+                } catch (Exception e) {
80
+                    JitsiMeetLogger.w(TAG + "error parsing participantsList", e);
81
+                }
82
+
83
+                break;
84
+        }
85
+    }
86
+
87
+    public interface ParticipantsInfoCallback {
88
+        void onReceived(List<ParticipantInfo> participantInfoList);
89
+    }
90
+}

+ 1
- 0
ios/sdk/src/ExternalAPI.h 查看文件

@@ -22,5 +22,6 @@
22 22
 - (void)sendSetAudioMuted: (BOOL)muted;
23 23
 - (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
24 24
 - (void)toggleScreenShare;
25
+- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
25 26
 
26 27
 @end

+ 37
- 2
ios/sdk/src/ExternalAPI.m 查看文件

@@ -22,9 +22,17 @@ static NSString * const hangUpAction = @"org.jitsi.meet.HANG_UP";
22 22
 static NSString * const setAudioMutedAction = @"org.jitsi.meet.SET_AUDIO_MUTED";
23 23
 static NSString * const sendEndpointTextMessageAction = @"org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE";
24 24
 static NSString * const toggleScreenShareAction = @"org.jitsi.meet.TOGGLE_SCREEN_SHARE";
25
+static NSString * const retrieveParticipantsInfoAction = @"org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO";
25 26
 
26 27
 @implementation ExternalAPI
27 28
 
29
+static NSMapTable<NSString*, void (^)(NSArray* participantsInfo)> *participantInfoCompletionHandlers;
30
+
31
+__attribute__((constructor))
32
+static void initializeViewsMap() {
33
+    participantInfoCompletionHandlers = [NSMapTable strongToWeakObjectsMapTable];
34
+}
35
+
28 36
 RCT_EXPORT_MODULE();
29 37
 
30 38
 - (NSDictionary *)constantsToExport {
@@ -32,7 +40,8 @@ RCT_EXPORT_MODULE();
32 40
         @"HANG_UP": hangUpAction,
33 41
         @"SET_AUDIO_MUTED" : setAudioMutedAction,
34 42
         @"SEND_ENDPOINT_TEXT_MESSAGE": sendEndpointTextMessageAction,
35
-        @"TOGGLE_SCREEN_SHARE": toggleScreenShareAction
43
+        @"TOGGLE_SCREEN_SHARE": toggleScreenShareAction,
44
+        @"RETRIEVE_PARTICIPANTS_INFO": retrieveParticipantsInfoAction
36 45
     };
37 46
 };
38 47
 
@@ -48,7 +57,11 @@ RCT_EXPORT_MODULE();
48 57
 }
49 58
 
50 59
 - (NSArray<NSString *> *)supportedEvents {
51
-    return @[ hangUpAction, setAudioMutedAction, sendEndpointTextMessageAction, toggleScreenShareAction ];
60
+    return @[ hangUpAction,
61
+              setAudioMutedAction,
62
+              sendEndpointTextMessageAction,
63
+              toggleScreenShareAction,
64
+              retrieveParticipantsInfoAction];
52 65
 }
53 66
 
54 67
 /**
@@ -76,6 +89,11 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
76 89
     if (!delegate) {
77 90
         return;
78 91
     }
92
+    
93
+    if ([name isEqual: @"PARTICIPANTS_INFO_RETRIEVED"]) {
94
+        [self onParticipantsInfoRetrieved: data];
95
+        return;
96
+    }
79 97
 
80 98
     SEL sel = NSSelectorFromString([self methodNameFromEventName:name]);
81 99
 
@@ -84,6 +102,15 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
84 102
     }
85 103
 }
86 104
 
105
+- (void) onParticipantsInfoRetrieved:(NSDictionary *)data {
106
+    NSArray *participantsInfoArray = [data objectForKey:@"participantsInfo"];
107
+    NSString *completionHandlerId = [data objectForKey:@"requestId"];
108
+    
109
+    void (^completionHandler)(NSArray*) = [participantInfoCompletionHandlers objectForKey:completionHandlerId];
110
+    completionHandler(participantsInfoArray);
111
+    [participantInfoCompletionHandlers removeObjectForKey:completionHandlerId];
112
+}
113
+
87 114
 /**
88 115
  * Converts a specific event name i.e. redux action type description to a
89 116
  * method name.
@@ -129,4 +156,12 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
129 156
     [self sendEventWithName:toggleScreenShareAction body:nil];
130 157
 }
131 158
 
159
+- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
160
+    NSString *completionHandlerId = [[NSUUID UUID] UUIDString];
161
+    NSDictionary *data = @{ @"requestId": completionHandlerId};
162
+    
163
+    [participantInfoCompletionHandlers setObject:completionHandler forKey:completionHandlerId];
164
+    
165
+    [self sendEventWithName:retrieveParticipantsInfoAction body:data];
166
+}
132 167
 @end

+ 2
- 0
ios/sdk/src/JitsiMeetView.h 查看文件

@@ -45,4 +45,6 @@
45 45
 
46 46
 - (void)toggleScreenShare;
47 47
 
48
+- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler;
49
+
48 50
 @end

+ 5
- 0
ios/sdk/src/JitsiMeetView.m 查看文件

@@ -135,6 +135,11 @@ static void initializeViewsMap() {
135 135
     [externalAPI toggleScreenShare];
136 136
 }
137 137
 
138
+- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
139
+    ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
140
+    [externalAPI retrieveParticipantsInfo:completionHandler];
141
+}
142
+
138 143
 #pragma mark Private methods
139 144
 
140 145
 /**

+ 34
- 2
react/features/mobile/external-api/middleware.js 查看文件

@@ -27,7 +27,7 @@ import {
27 27
 } from '../../base/connection';
28 28
 import { JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
29 29
 import { SET_AUDIO_MUTED } from '../../base/media/actionTypes';
30
-import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../../base/participants';
30
+import { PARTICIPANT_JOINED, PARTICIPANT_LEFT, getParticipants } from '../../base/participants';
31 31
 import { MiddlewareRegistry, StateListenerRegistry } from '../../base/redux';
32 32
 import { toggleScreensharing } from '../../base/tracks';
33 33
 import { muteLocal } from '../../remote-video-menu/actions';
@@ -55,6 +55,11 @@ const ENDPOINT_TEXT_MESSAGE_RECEIVED = 'ENDPOINT_TEXT_MESSAGE_RECEIVED';
55 55
  */
56 56
 const SCREEN_SHARE_TOGGLED = 'SCREEN_SHARE_TOGGLED';
57 57
 
58
+/**
59
+ * Event which will be emitted on the native side with the participant info array.
60
+ */
61
+const PARTICIPANTS_INFO_RETRIEVED = 'PARTICIPANTS_INFO_RETRIEVED';
62
+
58 63
 const { ExternalAPI } = NativeModules;
59 64
 const eventEmitter = new NativeEventEmitter(ExternalAPI);
60 65
 
@@ -158,7 +163,10 @@ MiddlewareRegistry.register(store => next => action => {
158 163
                 isLocal: participant.local,
159 164
                 email: participant.email,
160 165
                 name: participant.name,
161
-                participantId: participant.id
166
+                participantId: participant.id,
167
+                displayName: participant.displayName,
168
+                avatarUrl: participant.avatarURL,
169
+                role: participant.role
162 170
             });
163 171
         break;
164 172
     }
@@ -254,6 +262,30 @@ function _registerForNativeEvents({ getState, dispatch }) {
254 262
     eventEmitter.addListener(ExternalAPI.TOGGLE_SCREEN_SHARE, () => {
255 263
         dispatch(toggleScreensharing());
256 264
     });
265
+
266
+    eventEmitter.addListener(ExternalAPI.RETRIEVE_PARTICIPANTS_INFO, ({ requestId }) => {
267
+        const store = getState();
268
+
269
+        const participantsInfo = getParticipants(store).map(participant => {
270
+            return {
271
+                isLocal: participant.local,
272
+                email: participant.email,
273
+                name: participant.name,
274
+                participantId: participant.id,
275
+                displayName: participant.displayName,
276
+                avatarUrl: participant.avatarURL,
277
+                role: participant.role
278
+            };
279
+        });
280
+
281
+        sendEvent(
282
+            store,
283
+            PARTICIPANTS_INFO_RETRIEVED,
284
+            /* data */ {
285
+                participantsInfo,
286
+                requestId
287
+            });
288
+    });
257 289
 }
258 290
 
259 291
 /**

正在加载...
取消
保存