Browse Source

Merge pull request #75 from syanbo/feature/2.4.1-alpha.1

Feature integrate android & ios sdk 2.4.1
matrixbirds 5 years ago
parent
commit
367ba47569
No account linked to committer's email address

+ 14
- 0
CHANGELOG View File

1
 ## THE CHANGELOG
1
 ## THE CHANGELOG
2
 
2
 
3
+#### 2.4.1-alpha
4
+- support 2.4.1-alpha.1 agora video sdk android-2.4.1 / iOS-2.4.1
5
+  1. Deprecate iOS
6
+  2. Add methods getAudioMixingPlayoutVolume, getAudioMixingPublishVolume for audio mixing troubleshooting.
7
+  3. Add `txPacketLossRate`, `rxPacketLossRate` on `rtcStats` interface. usage: `RtcEngine.on('rtcStats', (data) => console.log(data))`.
8
+  4. Rename `receivedFrameRate` to `rendererOutputFrameRate` this property related on `localVideoStats` and `remoteVideoStats`.
9
+  5. Add event 'localVideoChanged' and Deprecate events `cameraReady` and `videoStopped`. You can listen `localVideoChanged` event instead  `cameraReady` & `videoStopped`.
10
+  6. Add event `rtmpStreamingStateChanged` for rtmp streaming troubleshooting
11
+  7. Add event `audioCodecProfile` on `liveTranscoding` interface.
12
+  8. Add event `networkTypeChanged` for network troubleshooting.
13
+  9. Add method `registerMediaMetadataObserver` method, this method enables you to add synchronized metadata in the video stream for more diversified live broadcast interactions, such as sending shopping links, digital coupons, and online quizzes. note: Call this method before the joinChannel method. and applies to `channelProfile` with 1. 
14
+  10. Add method `sendMediaData`, this method enables you send media data under the live broadcast mode (`channelProfile` = 1) note: call this method after the `registerMediaMetadataObserver` method.
15
+  11. Add event `audioMixingStateChanged` and Deprecate event 'localAudioMixingFinish`.
16
+  11. Add `firstRemoteAudioDecoded` event you can get more detail [here](https://docs.agora.io/en/Interactive%20Broadcast/release_android_video?platform=Android#v241)
3
 
17
 
4
 #### 2.4.0-alpha
18
 #### 2.4.0-alpha
5
 - support 2.4.0-alpha.1 agora video sdk android-2.4.0 / iOS-2.4.0.1 and add sendMessage support in the same channel. Deprecate: startEchoTest and setVideoQualityParameters
19
 - support 2.4.0-alpha.1 agora video sdk android-2.4.0 / iOS-2.4.0.1 and add sendMessage support in the same channel. Deprecate: startEchoTest and setVideoQualityParameters

+ 1
- 1
android/build.gradle View File

61
     def androidSupportVersion = rootProject.hasProperty("androidSupportVersion")  ? rootProject.androidSupportVersion : DEFAULT_ANDROID_SUPPORT_VERSION
61
     def androidSupportVersion = rootProject.hasProperty("androidSupportVersion")  ? rootProject.androidSupportVersion : DEFAULT_ANDROID_SUPPORT_VERSION
62
     // from internet
62
     // from internet
63
     implementation "com.android.support:appcompat-v7:$androidSupportVersion"
63
     implementation "com.android.support:appcompat-v7:$androidSupportVersion"
64
-    implementation "io.agora.rtc:full-sdk:2.4.0"
64
+    implementation "io.agora.rtc:full-sdk:2.4.1"
65
     // from node_modules
65
     // from node_modules
66
     implementation "com.facebook.react:react-native:+"
66
     implementation "com.facebook.react:react-native:+"
67
 }
67
 }

+ 1
- 0
android/src/main/java/com/syan/agora/AgoraManager.java View File

13
 import java.util.List;
13
 import java.util.List;
14
 import java.util.Map;
14
 import java.util.Map;
15
 
15
 
16
+import io.agora.rtc.IMetadataObserver;
16
 import io.agora.rtc.IRtcEngineEventHandler;
17
 import io.agora.rtc.IRtcEngineEventHandler;
17
 import io.agora.rtc.RtcEngine;
18
 import io.agora.rtc.RtcEngine;
18
 import io.agora.rtc.video.BeautyOptions;
19
 import io.agora.rtc.video.BeautyOptions;

+ 136
- 36
android/src/main/java/com/syan/agora/AgoraModule.java View File

17
 import com.facebook.react.modules.core.DeviceEventManagerModule;
17
 import com.facebook.react.modules.core.DeviceEventManagerModule;
18
 
18
 
19
 
19
 
20
+import java.nio.charset.Charset;
20
 import java.util.ArrayList;
21
 import java.util.ArrayList;
21
 import java.util.HashMap;
22
 import java.util.HashMap;
22
 import java.util.Map;
23
 import java.util.Map;
23
 
24
 
24
 import io.agora.rtc.Constants;
25
 import io.agora.rtc.Constants;
25
 import io.agora.rtc.IAudioEffectManager;
26
 import io.agora.rtc.IAudioEffectManager;
27
+import io.agora.rtc.IMetadataObserver;
26
 import io.agora.rtc.IRtcEngineEventHandler;
28
 import io.agora.rtc.IRtcEngineEventHandler;
27
 import io.agora.rtc.RtcEngine;
29
 import io.agora.rtc.RtcEngine;
28
 import io.agora.rtc.internal.LastmileProbeConfig;
30
 import io.agora.rtc.internal.LastmileProbeConfig;
285
     private final static String AGUserEnableVideo = "userEnableVideo";
287
     private final static String AGUserEnableVideo = "userEnableVideo";
286
     private final static String AGUserEnableLocalVideo = "userEnableLocalVideo";
288
     private final static String AGUserEnableLocalVideo = "userEnableLocalVideo";
287
     private final static String AGVideoSizeChanged = "videoSizeChanged";
289
     private final static String AGVideoSizeChanged = "videoSizeChanged";
290
+    private final static String AGRtmpStreamingStateChanged = "rtmpStreamingStateChanged";
291
+    private final static String AGNetworkTypeChanged = "networkTypeChanged";
292
+    private final static String AGFirstRemoteAudioDecoded = "firstRemoteAudioDecoded";
293
+    private final static String AGMediaMetaDataReceived = "mediaMetaDataReceived";
294
+    private final static String AGLocalVideoChanged = "localVideoChanged";
288
     private final static String AGRemoteVideoStateChanged = "remoteVideoStateChanged";
295
     private final static String AGRemoteVideoStateChanged = "remoteVideoStateChanged";
289
     private final static String AGLocalPublishFallbackToAudioOnly = "localPublishFallbackToAudioOnly";
296
     private final static String AGLocalPublishFallbackToAudioOnly = "localPublishFallbackToAudioOnly";
290
     private final static String AGRemoteSubscribeFallbackToAudioOnly = "remoteSubscribeFallbackToAudioOnly";
297
     private final static String AGRemoteSubscribeFallbackToAudioOnly = "remoteSubscribeFallbackToAudioOnly";
303
     private final static String AGAudioTransportStatsOfUid = "audioTransportStatsOfUid";
310
     private final static String AGAudioTransportStatsOfUid = "audioTransportStatsOfUid";
304
     private final static String AGVideoTransportStatsOfUid = "videoTransportStatsOfUid";
311
     private final static String AGVideoTransportStatsOfUid = "videoTransportStatsOfUid";
305
 
312
 
306
-    private final static String AGLocalAudioMixingFinish = "localAudioMixingFinish";
307
     private final static String AGRemoteAudioMixingStart = "remoteAudioMixingStart";
313
     private final static String AGRemoteAudioMixingStart = "remoteAudioMixingStart";
308
     private final static String AGRemoteAudioMixingFinish = "remoteAudioMixingFinish";
314
     private final static String AGRemoteAudioMixingFinish = "remoteAudioMixingFinish";
309
     private final static String AGAudioEffectFinish = "audioEffectFinish";
315
     private final static String AGAudioEffectFinish = "audioEffectFinish";
316
+    private final static String AGAudioMixingStateChanged = "audioMixingStateChanged";
310
 
317
 
311
     private final static String AGStreamPublished = "streamPublished";
318
     private final static String AGStreamPublished = "streamPublished";
312
     private final static String AGStreamUnpublish = "streamUnpublish";
319
     private final static String AGStreamUnpublish = "streamUnpublish";
322
     private final static String AGLastmileProbeResult = "lastmileProbeTestResult";
329
     private final static String AGLastmileProbeResult = "lastmileProbeTestResult";
323
 //    private final static String AGIntervalTest = "startEchoTestWithInterval";
330
 //    private final static String AGIntervalTest = "startEchoTestWithInterval";
324
 
331
 
332
+    private MediaObserver mediaObserver = null;
333
+
325
     private IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
334
     private IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
326
 
335
 
327
         @Override
336
         @Override
415
                     statsMap.putInt("userCount", stats.users);
424
                     statsMap.putInt("userCount", stats.users);
416
                     statsMap.putDouble("cpuAppUsage", stats.cpuAppUsage);
425
                     statsMap.putDouble("cpuAppUsage", stats.cpuAppUsage);
417
                     statsMap.putDouble("cpuTotalUsage", stats.cpuTotalUsage);
426
                     statsMap.putDouble("cpuTotalUsage", stats.cpuTotalUsage);
427
+                    statsMap.putInt("txPacketLossRate", stats.txPacketLossRate);
428
+                    statsMap.putInt("rxPacketLossRate", stats.rxPacketLossRate);
418
 
429
 
419
                     WritableMap map = Arguments.createMap();
430
                     WritableMap map = Arguments.createMap();
420
                     map.putMap("stats", statsMap);
431
                     map.putMap("stats", statsMap);
584
             });
595
             });
585
         }
596
         }
586
 
597
 
587
-        @Override
588
-        public void onVideoStopped() {
589
-            runOnUiThread(new Runnable() {
590
-                @Override
591
-                public void run() {
592
-                    WritableMap map = Arguments.createMap();
593
-                    map.putString("message", "VideoStopped");
594
-                    sendEvent(getReactApplicationContext(), AGVideoStopped, map);
595
-                }
596
-            });
597
-        }
598
-
599
         @Override
598
         @Override
600
         public void onFirstLocalVideoFrame(final int width, final int height, final int elapsed) {
599
         public void onFirstLocalVideoFrame(final int width, final int height, final int elapsed) {
601
             runOnUiThread(new Runnable() {
600
             runOnUiThread(new Runnable() {
710
             });
709
             });
711
         }
710
         }
712
 
711
 
712
+        @Override
713
+        public void onRtmpStreamingStateChanged(final String url, final int state, final int errCode) {
714
+            runOnUiThread(new Runnable() {
715
+                @Override
716
+                public void run() {
717
+                    WritableMap map = Arguments.createMap();
718
+                    map.putString("url", url);
719
+                    map.putInt("state", state);
720
+                    map.putInt("errorCode", errCode);
721
+                    sendEvent(getReactApplicationContext(), AGRtmpStreamingStateChanged, map);
722
+                }
723
+            });
724
+        }
725
+
726
+        @Override
727
+        public void onNetworkTypeChanged(final int type) {
728
+            runOnUiThread(new Runnable() {
729
+                @Override
730
+                public void run() {
731
+                    WritableMap map = Arguments.createMap();
732
+                    map.putInt("type", type);
733
+                    sendEvent(getReactApplicationContext(), AGNetworkTypeChanged, map);
734
+                }
735
+            });
736
+        }
737
+
738
+        @Override
739
+        public void onFirstRemoteAudioDecoded(final int uid, final int elapsed) {
740
+            runOnUiThread(new Runnable() {
741
+                @Override
742
+                public void run() {
743
+                    WritableMap map = Arguments.createMap();
744
+                    map.putInt("uid", uid);
745
+                    map.putInt("elapsed", elapsed);
746
+                    sendEvent(getReactApplicationContext(), AGFirstRemoteAudioDecoded, map);
747
+                }
748
+            });
749
+        }
750
+
713
         @Override
751
         @Override
714
         public void onRemoteVideoStateChanged(final int uid, final int state) {
752
         public void onRemoteVideoStateChanged(final int uid, final int state) {
715
             runOnUiThread(new Runnable() {
753
             runOnUiThread(new Runnable() {
760
             });
798
             });
761
         }
799
         }
762
 
800
 
763
-        @Override
764
-        public void onCameraReady() {
765
-            runOnUiThread(new Runnable() {
766
-                @Override
767
-                public void run() {
768
-                    WritableMap map = Arguments.createMap();
769
-                    map.putString("message", "CameraDidReady");
770
-                    sendEvent(getReactApplicationContext(), AGCameraReady, map);
771
-                }
772
-            });
773
-        }
774
-
775
         @Override
801
         @Override
776
         public void onCameraFocusAreaChanged(final Rect rect) {
802
         public void onCameraFocusAreaChanged(final Rect rect) {
777
             runOnUiThread(new Runnable() {
803
             runOnUiThread(new Runnable() {
841
                     statsMap.putInt("userCount", stats.users);
867
                     statsMap.putInt("userCount", stats.users);
842
                     statsMap.putDouble("cpuAppUsage", stats.cpuAppUsage);
868
                     statsMap.putDouble("cpuAppUsage", stats.cpuAppUsage);
843
                     statsMap.putDouble("cpuTotalUsage", stats.cpuTotalUsage);
869
                     statsMap.putDouble("cpuTotalUsage", stats.cpuTotalUsage);
870
+                    statsMap.putInt("txPacketLossRate", stats.txPacketLossRate);
871
+                    statsMap.putInt("rxPacketLossRate", stats.rxPacketLossRate);
844
 
872
 
845
                     WritableMap map = Arguments.createMap();
873
                     WritableMap map = Arguments.createMap();
846
                     map.putMap("stats", statsMap);
874
                     map.putMap("stats", statsMap);
884
                     WritableMap statsMap = Arguments.createMap();
912
                     WritableMap statsMap = Arguments.createMap();
885
                     statsMap.putInt("sentBitrate", stats.sentBitrate);
913
                     statsMap.putInt("sentBitrate", stats.sentBitrate);
886
                     statsMap.putInt("sentFrameRate", stats.sentFrameRate);
914
                     statsMap.putInt("sentFrameRate", stats.sentFrameRate);
887
-
915
+                    statsMap.putInt("encoderOutputFrameRate", stats.encoderOutputFrameRate);
916
+                    statsMap.putInt("rendererOutputFrameRate", stats.rendererOutputFrameRate);
888
                     WritableMap map = Arguments.createMap();
917
                     WritableMap map = Arguments.createMap();
889
                     map.putMap("stats", statsMap);
918
                     map.putMap("stats", statsMap);
890
                     sendEvent(getReactApplicationContext(), AGLocalVideoStats, map);
919
                     sendEvent(getReactApplicationContext(), AGLocalVideoStats, map);
902
                     statsMap.putInt("width", stats.width);
931
                     statsMap.putInt("width", stats.width);
903
                     statsMap.putInt("height", stats.height);
932
                     statsMap.putInt("height", stats.height);
904
                     statsMap.putInt("receivedBitrate", stats.receivedBitrate);
933
                     statsMap.putInt("receivedBitrate", stats.receivedBitrate);
905
-                    statsMap.putInt("receivedFrameRate", stats.receivedFrameRate);
934
+                    statsMap.putInt("rendererOutputFrameRate", stats.rendererOutputFrameRate);
906
                     statsMap.putInt("rxStreamType", stats.rxStreamType);
935
                     statsMap.putInt("rxStreamType", stats.rxStreamType);
907
                     WritableMap map = Arguments.createMap();
936
                     WritableMap map = Arguments.createMap();
908
                     map.putMap("stats", statsMap);
937
                     map.putMap("stats", statsMap);
952
         }
981
         }
953
 
982
 
954
         @Override
983
         @Override
955
-        public void onAudioMixingFinished() {
984
+        public void onAudioMixingStateChanged(final int state, final int errorCode) {
956
             runOnUiThread(new Runnable() {
985
             runOnUiThread(new Runnable() {
957
                 @Override
986
                 @Override
958
                 public void run() {
987
                 public void run() {
959
                     WritableMap map = Arguments.createMap();
988
                     WritableMap map = Arguments.createMap();
960
-                    map.putString("message", "LocalAudioMixingSucceedFinish");
961
-                    sendEvent(getReactApplicationContext(), AGLocalAudioMixingFinish, map);
989
+                    map.putInt("state", state);
990
+                    map.putInt("errorCode", errorCode);
991
+                    sendEvent(getReactApplicationContext(), AGAudioMixingStateChanged, map);
962
                 }
992
                 }
963
             });
993
             });
964
         }
994
         }
1034
             runOnUiThread(new Runnable() {
1064
             runOnUiThread(new Runnable() {
1035
                 @Override
1065
                 @Override
1036
                 public void run() {
1066
                 public void run() {
1037
-                    String msg = new String(data);
1067
+                    String msg = new String(data, Charset.forName("UTF-8"));
1038
                     WritableMap map = Arguments.createMap();
1068
                     WritableMap map = Arguments.createMap();
1039
                     map.putInt("uid", uid);
1069
                     map.putInt("uid", uid);
1040
                     map.putInt("streamId", streamId);
1070
                     map.putInt("streamId", streamId);
1096
                 }
1126
                 }
1097
             });
1127
             });
1098
         }
1128
         }
1129
+
1130
+        @Override
1131
+        public void onLocalVideoStateChanged(final int localVideoState, final int error) {
1132
+            super.onLocalVideoStateChanged(localVideoState, error);
1133
+            runOnUiThread(new Runnable() {
1134
+                @Override
1135
+                public void run() {
1136
+                    WritableMap map = Arguments.createMap();
1137
+                    map.putString("message", "LocalVideoChanged");
1138
+                    map.putInt("state", localVideoState);
1139
+                    sendEvent(getReactApplicationContext(), AGLocalVideoChanged, map);
1140
+                }
1141
+            });
1142
+        }
1099
     };
1143
     };
1100
 
1144
 
1101
     @ReactMethod
1145
     @ReactMethod
1713
         }
1757
         }
1714
     }
1758
     }
1715
 
1759
 
1760
+    @ReactMethod
1761
+    public void getAudioMixingPlayoutVolume(Promise promise) {
1762
+        try {
1763
+            int res = AgoraManager.getInstance().mRtcEngine.getAudioMixingPlayoutVolume();
1764
+            if (res < 0) throw new ReactNativeAgoraException("getAudioMixingPlayoutVolume Failed", res);
1765
+            WritableMap map = Arguments.createMap();
1766
+            map.putBoolean("success", true);
1767
+            map.putInt("value", res);
1768
+            promise.resolve(map);
1769
+        } catch (Exception e) {
1770
+            promise.reject("-1", e);
1771
+        }
1772
+    }
1773
+
1774
+    @ReactMethod
1775
+    public void getAudioMixingPublishVolume(Promise promise) {
1776
+        try {
1777
+            int res = AgoraManager.getInstance().mRtcEngine.getAudioMixingPlayoutVolume();
1778
+            if (res < 0) throw new ReactNativeAgoraException("getAudioMixingPublishVolume Failed", res);
1779
+            WritableMap map = Arguments.createMap();
1780
+            map.putBoolean("success", true);
1781
+            map.putInt("value", res);
1782
+            promise.resolve(map);
1783
+        } catch (Exception e) {
1784
+            promise.reject("-1", e);
1785
+        }
1786
+    }
1787
+
1716
     @ReactMethod
1788
     @ReactMethod
1717
     public void getAudioMixingDuration(Promise promise) {
1789
     public void getAudioMixingDuration(Promise promise) {
1718
         try {
1790
         try {
1723
             map.putInt("value", res);
1795
             map.putInt("value", res);
1724
             promise.resolve(map);
1796
             promise.resolve(map);
1725
         } catch (Exception e) {
1797
         } catch (Exception e) {
1726
-            promise.reject("131004", e);
1798
+            promise.reject("-1", e);
1727
         }
1799
         }
1728
     }
1800
     }
1729
 
1801
 
2007
             map.putInt("value", res);
2079
             map.putInt("value", res);
2008
             promise.resolve(map);
2080
             promise.resolve(map);
2009
         } catch (Exception e) {
2081
         } catch (Exception e) {
2010
-            promise.reject("131030", e);
2082
+            promise.reject("-1", e);
2083
+        }
2084
+    }
2085
+
2086
+    @ReactMethod
2087
+    public void sendMediaData(String data, final Promise promise) {
2088
+        if (null == mediaObserver) {
2089
+            promise.reject("-1", "sendMediaData failed");
2090
+        } else {
2091
+            mediaObserver.setMetadata(data.getBytes(Charset.forName("UTF-8")));
2092
+            WritableMap map = Arguments.createMap();
2093
+            map.putBoolean("success", true);
2094
+            promise.resolve(map);
2095
+        }
2096
+    }
2097
+
2098
+    @ReactMethod
2099
+    public void registerMediaMetadataObserver(final Promise promise) {
2100
+        try {
2101
+            mediaObserver = new MediaObserver(getReactApplicationContext());
2102
+            int res = AgoraManager.getInstance().mRtcEngine
2103
+                    .registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA);
2104
+            if (res < 0) {
2105
+                new ReactNativeAgoraException("registerMediaMetadataObserver Failed", res);
2106
+            }
2107
+            WritableMap map = Arguments.createMap();
2108
+            map.putBoolean("success", true);
2109
+            map.putInt("value", res);
2110
+            promise.resolve(map);
2111
+        } catch (Exception e) {
2112
+            promise.reject("-1", e);
2011
         }
2113
         }
2012
     }
2114
     }
2013
 
2115
 
2443
             String data = options.getString("data");
2545
             String data = options.getString("data");
2444
             int streamID = AgoraManager.getInstance().mRtcEngine.createDataStream(reliable, ordered);
2546
             int streamID = AgoraManager.getInstance().mRtcEngine.createDataStream(reliable, ordered);
2445
             if (streamID < 0) throw new ReactNativeAgoraException("createDataStream Failed", streamID);
2547
             if (streamID < 0) throw new ReactNativeAgoraException("createDataStream Failed", streamID);
2446
-            int res = AgoraManager.getInstance().mRtcEngine.sendStreamMessage(streamID, data.getBytes("utf8"));
2548
+            int res = AgoraManager.getInstance().mRtcEngine.sendStreamMessage(streamID, data.getBytes(Charset.forName("UTF-8")));
2447
             if (res != 0) throw new ReactNativeAgoraException("sendStreamMessage Failed", res);
2549
             if (res != 0) throw new ReactNativeAgoraException("sendStreamMessage Failed", res);
2448
             WritableMap map = Arguments.createMap();
2550
             WritableMap map = Arguments.createMap();
2449
             map.putBoolean("success", true);
2551
             map.putBoolean("success", true);
2635
     }
2737
     }
2636
 
2738
 
2637
 
2739
 
2638
-
2639
     @ReactMethod
2740
     @ReactMethod
2640
 
2741
 
2641
     private void sendEvent(ReactContext reactContext,
2742
     private void sendEvent(ReactContext reactContext,
2645
                 .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
2746
                 .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
2646
                 .emit(eventName, params);
2747
                 .emit(eventName, params);
2647
     }
2748
     }
2648
-
2649
 }
2749
 }

+ 59
- 0
android/src/main/java/com/syan/agora/MediaObserver.java View File

1
+package com.syan.agora;
2
+
3
+import com.facebook.react.bridge.Arguments;
4
+import com.facebook.react.bridge.ReactContext;
5
+import com.facebook.react.bridge.WritableMap;
6
+import com.facebook.react.modules.core.DeviceEventManagerModule;
7
+
8
+import java.nio.charset.Charset;
9
+
10
+import io.agora.rtc.IMetadataObserver;
11
+
12
+public class MediaObserver implements IMetadataObserver {
13
+
14
+    private static final Integer MAX_DATA_LENGT = 1024;
15
+
16
+    private ReactContext reactCtx;
17
+
18
+    public byte[] getMetadata() {
19
+        return metadata;
20
+    }
21
+
22
+    public void setMetadata(byte[] metadata) {
23
+        this.metadata = metadata;
24
+    }
25
+
26
+    private byte[] metadata = null;
27
+
28
+    public MediaObserver(ReactContext reactCtx) {
29
+        this.reactCtx = reactCtx;
30
+    }
31
+
32
+    @Override
33
+    public int getMaxMetadataSize() {
34
+        return MAX_DATA_LENGT;
35
+    }
36
+
37
+    @Override
38
+    public byte[] onReadyToSendMetadata(long timeStampMs) {
39
+        if (metadata == null) {
40
+            return null;
41
+        }
42
+        byte[] toSend = metadata;
43
+        if (toSend.length > MAX_DATA_LENGT) {
44
+            return null;
45
+        }
46
+        metadata = null;
47
+        return toSend;
48
+    }
49
+
50
+    @Override
51
+    public void onMetadataReceived(byte[] buffer, int uid, long timeStampMs) {
52
+        WritableMap map = Arguments.createMap();
53
+        map.putString("data", new String(buffer, Charset.forName("UTF-8")));
54
+        map.putString("uid", Integer.toString(uid));
55
+        map.putString("ts", Long.toString(timeStampMs));
56
+        reactCtx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
57
+                .emit("mediaMetaDataReceived", map);
58
+    }
59
+}

+ 6
- 1
ios/RCTAgora/AgoraConst.h View File

29
 static NSString *AGActiveSpeaker = @"activeSpeaker";
29
 static NSString *AGActiveSpeaker = @"activeSpeaker";
30
 static NSString *AGFirstLocalAudioFrame = @"firstLocalAudioFrame";
30
 static NSString *AGFirstLocalAudioFrame = @"firstLocalAudioFrame";
31
 static NSString *AGFirstRemoteAudioFrame = @"firstRemoteAudioFrame";
31
 static NSString *AGFirstRemoteAudioFrame = @"firstRemoteAudioFrame";
32
+static NSString *AGFirstRemoteAudioDecoded = @"firstRemoteAudioDecoded";
32
 static NSString *AGVideoStopped = @"videoStopped";
33
 static NSString *AGVideoStopped = @"videoStopped";
33
 static NSString *AGFirstLocalVideoFrame = @"firstLocalVideoFrame";
34
 static NSString *AGFirstLocalVideoFrame = @"firstLocalVideoFrame";
34
 static NSString *AGFirstRemoteVideoDecoded = @"firstRemoteVideoDecoded";
35
 static NSString *AGFirstRemoteVideoDecoded = @"firstRemoteVideoDecoded";
56
 static NSString *AGAudioTransportStatsOfUid = @"audioTransportStatsOfUid";
57
 static NSString *AGAudioTransportStatsOfUid = @"audioTransportStatsOfUid";
57
 static NSString *AGVideoTransportStatsOfUid = @"videoTransportStatsOfUid";
58
 static NSString *AGVideoTransportStatsOfUid = @"videoTransportStatsOfUid";
58
 
59
 
59
-static NSString *AGLocalAudioMixingFinish = @"localAudioMixingFinish";
60
 static NSString *AGRemoteAudioMixingStart = @"remoteAudioMixingStart";
60
 static NSString *AGRemoteAudioMixingStart = @"remoteAudioMixingStart";
61
 static NSString *AGRemoteAudioMixingFinish = @"remoteAudioMixingFinish";
61
 static NSString *AGRemoteAudioMixingFinish = @"remoteAudioMixingFinish";
62
 static NSString *AGAudioEffectFinish = @"audioEffectFinish";
62
 static NSString *AGAudioEffectFinish = @"audioEffectFinish";
77
 static NSString *AGAudioMixingStateChanged = @"audioMixingStateChanged";
77
 static NSString *AGAudioMixingStateChanged = @"audioMixingStateChanged";
78
 static NSString *AGLastmileProbeTestResult = @"lastmileProbeTestResult";
78
 static NSString *AGLastmileProbeTestResult = @"lastmileProbeTestResult";
79
 
79
 
80
+static NSString *AGRtmpStreamingStateChanged = @"rtmpStreamingStateChanged";
81
+static NSString *AGLocalVideoChanged = @"localVideoChanged";
82
+static NSString *AGNetworkTypeChanged = @"networkTypeChanged";
83
+static NSString *AGMediaMetaDataReceived = @"mediaMetaDataReceived";
84
+
80
 typedef NS_ENUM(NSInteger, AgoraModeType) {
85
 typedef NS_ENUM(NSInteger, AgoraModeType) {
81
   AgoraAudioMode,
86
   AgoraAudioMode,
82
   AgoraVideoMode
87
   AgoraVideoMode

+ 6
- 2
ios/RCTAgora/RCTAgora.h View File

10
 #import <UIKit/UIKit.h>
10
 #import <UIKit/UIKit.h>
11
 #import <React/RCTBridgeModule.h>
11
 #import <React/RCTBridgeModule.h>
12
 #import <React/RCTEventEmitter.h>
12
 #import <React/RCTEventEmitter.h>
13
+#import <AgoraRtcEngineKit/AgoraRtcEngineKit.h>
13
 
14
 
14
-@interface RCTAgora : RCTEventEmitter<RCTBridgeModule>
15
-
15
+@interface RCTAgora : RCTEventEmitter<RCTBridgeModule, AgoraMediaMetadataDelegate, AgoraMediaMetadataDataSource>
16
+- (void) sendEvent:(NSString *)msg params:(NSDictionary *)params;
17
+- (NSInteger) metadataMaxSize;
18
+- (NSData *_Nullable)readyToSendMetadataAtTimestamp:(NSTimeInterval)timestamp;
19
+- (void)receiveMetadata:(NSData *_Nonnull)data fromUser:(NSInteger)uid atTimestamp:(NSTimeInterval)timestamp;
16
 @end
20
 @end

+ 159
- 25
ios/RCTAgora/RCTAgora.m View File

13
 #import <React/RCTView.h>
13
 #import <React/RCTView.h>
14
 #import "AgoraConst.h"
14
 #import "AgoraConst.h"
15
 
15
 
16
+#define MAX_DATA_LENGTH 1024
17
+
16
 @interface RCTAgora ()
18
 @interface RCTAgora ()
17
 @property (strong, nonatomic) AgoraRtcEngineKit *rtcEngine;
19
 @property (strong, nonatomic) AgoraRtcEngineKit *rtcEngine;
18
-
20
+@property (strong, nonatomic) NSData *metadata;
19
 @end
21
 @end
20
 
22
 
21
 @implementation RCTAgora {
23
 @implementation RCTAgora {
27
   return YES;
29
   return YES;
28
 }
30
 }
29
 
31
 
32
+
33
+- (NSInteger) metadataMaxSize {
34
+  return MAX_DATA_LENGTH;
35
+}
36
+
37
+- (NSData *_Nullable)readyToSendMetadataAtTimestamp:(NSTimeInterval)timestamp
38
+{
39
+  if (nil == _metadata) {
40
+    return nil;
41
+  }
42
+  NSData *toSend = [_metadata copy];
43
+  if ([toSend length] > MAX_DATA_LENGTH) {
44
+    return nil;
45
+  }
46
+  _metadata = nil;
47
+  return toSend;
48
+}
49
+
50
+- (void)receiveMetadata:(NSData *_Nonnull)data fromUser:(NSInteger)uid atTimestamp:(NSTimeInterval)timestamp {
51
+  NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
52
+  [self sendEvent:AGMediaMetaDataReceived params:@{
53
+                                               @"uid": @(uid),
54
+                                               @"data": dataStr,
55
+                                               @"ts": @(timestamp)
56
+                                               }];
57
+}
58
+
59
+
30
 RCT_EXPORT_MODULE();
60
 RCT_EXPORT_MODULE();
31
 
61
 
32
 - (NSError *) makeNSError:(NSDictionary *)options {
62
 - (NSError *) makeNSError:(NSDictionary *)options {
594
                   reject:(RCTPromiseRejectBlock)reject) {
624
                   reject:(RCTPromiseRejectBlock)reject) {
595
   NSInteger res = [self.rtcEngine getAudioMixingDuration];
625
   NSInteger res = [self.rtcEngine getAudioMixingDuration];
596
   if (res != 0) {
626
   if (res != 0) {
597
-    reject(@"131004", @"getAudioMixingDuration failed", [self makeNSError:@{
598
-                                                                            @"code": @(131004),
627
+    reject(@"-1", @"getAudioMixingDuration failed", [self makeNSError:@{
628
+                                                                            @"code": @(-1),
599
                                                                             @"message":@{
629
                                                                             @"message":@{
600
                                                                                 @"success": @(NO),
630
                                                                                 @"success": @(NO),
601
                                                                                 @"value":[NSNumber numberWithInteger:res]
631
                                                                                 @"value":[NSNumber numberWithInteger:res]
609
   }
639
   }
610
 }
640
 }
611
 
641
 
642
+// get the volume of local audio mixing
643
+RCT_EXPORT_METHOD(getAudioMixingPlayoutVolume
644
+                  :(RCTPromiseResolveBlock)resolve
645
+                  reject:(RCTPromiseRejectBlock)reject) {
646
+  int res = [_rtcEngine getAudioMixingPlayoutVolume];
647
+  if (res < 0) {
648
+    reject(@"-1", @"getAudioMixingPlayoutVolume failed", [self makeNSError:@{
649
+                                                                            @"code": @(-1),
650
+                                                                            @"message":@{
651
+                                                                                @"success": @(NO),
652
+                                                                                @"value":[NSNumber numberWithInteger:res]
653
+                                                                                }
654
+                                                                            }]);
655
+  } else {
656
+    resolve(@{
657
+              @"success": @(YES),
658
+              @"value": @(res)
659
+              });
660
+  }
661
+}
662
+
663
+// get the volume of remote audio mixing
664
+RCT_EXPORT_METHOD(getAudioMixingPublishVolume
665
+                  :(RCTPromiseResolveBlock)resolve
666
+                  reject:(RCTPromiseRejectBlock)reject) {
667
+  int res = [_rtcEngine getAudioMixingPublishVolume];
668
+  if (res < 0) {
669
+    reject(@"-1", @"getAudioMixingPublishVolume failed", [self makeNSError:@{
670
+                                                                             @"code": @(-1),
671
+                                                                             @"message":@{
672
+                                                                                 @"success": @(NO),
673
+                                                                                 @"value":[NSNumber numberWithInteger:res]
674
+                                                                                 }
675
+                                                                             }]);
676
+  } else {
677
+    resolve(@{
678
+              @"success": @(YES),
679
+              @"value": @(res)
680
+              });
681
+  }
682
+}
683
+
684
+
612
 // get audio mixing current position
685
 // get audio mixing current position
613
 RCT_EXPORT_METHOD(getAudioMixingCurrentPosition
686
 RCT_EXPORT_METHOD(getAudioMixingCurrentPosition
614
                   :(RCTPromiseResolveBlock)resolve
687
                   :(RCTPromiseResolveBlock)resolve
1631
   if (options[@"videoCodecProfile"] != nil) {
1704
   if (options[@"videoCodecProfile"] != nil) {
1632
     transcoding.videoCodecProfile = (AgoraVideoCodecProfileType)[options[@"videoCodecProfile"] integerValue];
1705
     transcoding.videoCodecProfile = (AgoraVideoCodecProfileType)[options[@"videoCodecProfile"] integerValue];
1633
   }
1706
   }
1707
+  if (options[@"audioCodecProfile"] != nil) {
1708
+    transcoding.audioCodecProfile = (AgoraAudioCodecProfileType)[options[@"audioCodecProfile"] integerValue];
1709
+  }
1634
   if (options[@"transcodingUsers"] != nil) {
1710
   if (options[@"transcodingUsers"] != nil) {
1635
     NSMutableArray<AgoraLiveTranscodingUser*> *transcodingUsers = [NSMutableArray new];
1711
     NSMutableArray<AgoraLiveTranscodingUser*> *transcodingUsers = [NSMutableArray new];
1636
     for (NSDictionary *optionUser in options[@"users"]) {
1712
     for (NSDictionary *optionUser in options[@"users"]) {
1885
   }
1961
   }
1886
 }
1962
 }
1887
 
1963
 
1964
+RCT_EXPORT_METHOD(sendMediaData:(NSString *)dataStr
1965
+                  resolve:(RCTPromiseResolveBlock)resolve
1966
+                  reject:(RCTPromiseRejectBlock)reject) {
1967
+  if ([self respondsToSelector:@selector(readyToSendMetadataAtTimestamp:)]) {
1968
+    self.metadata = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
1969
+    resolve(@{
1970
+              @"success": @(YES)
1971
+              });
1972
+  } else {
1973
+    reject(@"-1", @"sendMediaData failed", [self makeNSError:@{
1974
+                                                        @"code": @(-1),
1975
+                                                        @"message":@{
1976
+                                                          @"success": @(NO),
1977
+                                                        }}]);
1978
+  }
1979
+}
1980
+
1981
+RCT_EXPORT_METHOD(registerMediaMetadataObserver
1982
+                  :(RCTPromiseResolveBlock)resolve
1983
+                  reject:(RCTPromiseRejectBlock)reject) {
1984
+  if (YES == [_rtcEngine setMediaMetadataDataSource:self withType:AgoraMetadataTypeVideo] &&
1985
+    YES == [_rtcEngine setMediaMetadataDelegate:self withType:AgoraMetadataTypeVideo]
1986
+    ) {
1987
+    resolve(@{
1988
+              @"success": @(YES)
1989
+              });
1990
+  } else {
1991
+    reject(@"-1", @"registerMediaMetadataObserver failed", [self makeNSError:@{
1992
+                                                                             @"code": @(-1),
1993
+                                                                             @"message":@{
1994
+                                                                                 @"success": @(NO),
1995
+                                                                                 @"value":@(0)
1996
+                                                                                 }
1997
+                                                                             }]);
1998
+  }
1999
+}
2000
+
1888
 - (NSArray<NSString *> *)supportedEvents {
2001
 - (NSArray<NSString *> *)supportedEvents {
1889
   return @[
2002
   return @[
1890
            AGWarning,
2003
            AGWarning,
1906
            AGActiveSpeaker,
2019
            AGActiveSpeaker,
1907
            AGFirstLocalAudioFrame,
2020
            AGFirstLocalAudioFrame,
1908
            AGFirstRemoteAudioFrame,
2021
            AGFirstRemoteAudioFrame,
2022
+           AGFirstRemoteAudioDecoded,
1909
            AGVideoStopped,
2023
            AGVideoStopped,
1910
            AGFirstLocalVideoFrame,
2024
            AGFirstLocalVideoFrame,
1911
            AGFirstRemoteVideoDecoded,
2025
            AGFirstRemoteVideoDecoded,
1933
            AGAudioTransportStatsOfUid,
2047
            AGAudioTransportStatsOfUid,
1934
            AGVideoTransportStatsOfUid,
2048
            AGVideoTransportStatsOfUid,
1935
            
2049
            
1936
-           AGLocalAudioMixingFinish,
2050
+           AGAudioMixingStateChanged,
1937
            AGRemoteAudioMixingStart,
2051
            AGRemoteAudioMixingStart,
1938
            AGRemoteAudioMixingFinish,
2052
            AGRemoteAudioMixingFinish,
1939
            AGAudioEffectFinish,
2053
            AGAudioEffectFinish,
1950
            AGMediaEngineLoaded,
2064
            AGMediaEngineLoaded,
1951
            AGMediaEngineStartCall,
2065
            AGMediaEngineStartCall,
1952
            AGIntervalTest,
2066
            AGIntervalTest,
1953
-           AGAudioMixingStateChanged,
1954
-           AGLastmileProbeTestResult
2067
+           AGLastmileProbeTestResult,
2068
+           AGRtmpStreamingStateChanged,
2069
+           AGLocalVideoChanged,
2070
+           AGNetworkTypeChanged,
2071
+           AGFirstRemoteAudioFrame,
2072
+           AGMediaMetaDataReceived
1955
            ];
2073
            ];
1956
 }
2074
 }
1957
 
2075
 
2050
                                            }];
2168
                                            }];
2051
 }
2169
 }
2052
 
2170
 
2171
+- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine networkTypeChangedToType:(AgoraNetworkType)type {
2172
+  [self sendEvent:AGNetworkTypeChanged params:@{
2173
+                                                @"type": @(type)
2174
+                                                }];
2175
+}
2176
+
2053
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine connectionChangedToState:(AgoraConnectionStateType)state reason:(AgoraConnectionChangedReason)reason {
2177
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine connectionChangedToState:(AgoraConnectionStateType)state reason:(AgoraConnectionChangedReason)reason {
2054
   [self sendEvent:AGConnectionStateChanged params:@{
2178
   [self sendEvent:AGConnectionStateChanged params:@{
2055
                                                     @"state": @(state),
2179
                                                     @"state": @(state),
2114
                                                       }];
2238
                                                       }];
2115
 }
2239
 }
2116
 
2240
 
2117
-- (void)rtcEngineVideoDidStop:(AgoraRtcEngineKit *_Nonnull)engine {
2118
-  [self sendEvent:AGVideoStopped params:@{
2119
-                                        @"message": @"VideoStopped"
2120
-                                        }];
2241
+- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine firstRemoteAudioFrameDecodedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed {
2242
+  [self sendEvent:AGFirstRemoteAudioDecoded params:@{
2243
+                                                     @"uid": @(uid),
2244
+                                                     @"elapsed": @(elapsed)
2245
+                                                     }];
2121
 }
2246
 }
2122
 
2247
 
2123
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine firstLocalVideoFrameWithSize:(CGSize)size elapsed:(NSInteger)elapsed {
2248
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine firstLocalVideoFrameWithSize:(CGSize)size elapsed:(NSInteger)elapsed {
2208
                                                 }];
2333
                                                 }];
2209
 }
2334
 }
2210
 
2335
 
2211
-- (void)rtcEngineCameraDidReady:(AgoraRtcEngineKit *_Nonnull)engine {
2212
-  [self sendEvent:AGCameraReady params:@{
2213
-                                          @"message": @"CameraDidReady"
2214
-                                          }];
2215
-}
2216
-
2217
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine cameraFocusDidChangedToRect:(CGRect)rect {
2336
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine cameraFocusDidChangedToRect:(CGRect)rect {
2218
   [self sendEvent:AGCameraFocusAreaChanged params:@{
2337
   [self sendEvent:AGCameraFocusAreaChanged params:@{
2219
                                                        @"rect": @(rect)
2338
                                                        @"rect": @(rect)
2242
   [self sendEvent:AGRtcStats params:@{
2361
   [self sendEvent:AGRtcStats params:@{
2243
                                           @"stats": @{
2362
                                           @"stats": @{
2244
                                               @"duration": @(stats.duration),
2363
                                               @"duration": @(stats.duration),
2364
+                                              @"txPacketLossRate": @(stats.txPacketLossRate),
2365
+                                              @"rxPacketLossRate": @(stats.rxPacketLossRate),
2245
                                               @"txBytes": @(stats.txBytes),
2366
                                               @"txBytes": @(stats.txBytes),
2246
                                               @"rxBytes": @(stats.rxBytes),
2367
                                               @"rxBytes": @(stats.rxBytes),
2247
                                               @"txAudioKBitrate": @(stats.txAudioKBitrate),
2368
                                               @"txAudioKBitrate": @(stats.txAudioKBitrate),
2275
                                            @"stats": @{
2396
                                            @"stats": @{
2276
                                                @"sentBitrate": @(stats.sentBitrate),
2397
                                                @"sentBitrate": @(stats.sentBitrate),
2277
                                                @"sentFrameRate": @(stats.sentFrameRate)
2398
                                                @"sentFrameRate": @(stats.sentFrameRate)
2278
-                                               }
2399
+                                               },
2400
+                                           @"encoderOutputFrameRate": @(stats.encoderOutputFrameRate),
2401
+                                           @"rendererOutputFrameRate":
2402
+                                               @(stats.rendererOutputFrameRate)
2279
                                            }];
2403
                                            }];
2280
 }
2404
 }
2281
 
2405
 
2286
                                                 @"width": @(stats.width),
2410
                                                 @"width": @(stats.width),
2287
                                                 @"height": @(stats.height),
2411
                                                 @"height": @(stats.height),
2288
                                                 @"receivedBitrate": @(stats.receivedBitrate),
2412
                                                 @"receivedBitrate": @(stats.receivedBitrate),
2289
-                                                @"receivedFrameRate": @(stats.receivedFrameRate),
2290
-                                                @"rxStreamType": @(stats.rxStreamType)
2413
+                                                @"rendererOutputFrameRate": @(stats.rendererOutputFrameRate),
2414
+                                                @"rxStreamType": @(stats.rxStreamType),
2415
+                                                @"decoderOutputFrameRate": @(stats.decoderOutputFrameRate)
2291
                                                 }
2416
                                                 }
2292
                                             }];
2417
                                             }];
2293
 }
2418
 }
2310
                                                     }];
2435
                                                     }];
2311
 }
2436
 }
2312
 
2437
 
2313
-- (void)rtcEngineLocalAudioMixingDidFinish:(AgoraRtcEngineKit *_Nonnull)engine {
2314
-  [self sendEvent:AGLocalAudioMixingFinish params:@{
2315
-                                                     @"message": @"LocalAudioMixingSucceedFinish"
2316
-                                                     }];
2317
-}
2318
-
2319
 - (void)rtcEngineRemoteAudioMixingDidStart:(AgoraRtcEngineKit *_Nonnull)engine {
2438
 - (void)rtcEngineRemoteAudioMixingDidStart:(AgoraRtcEngineKit *_Nonnull)engine {
2320
   [self sendEvent:AGRemoteAudioMixingStart params:@{
2439
   [self sendEvent:AGRemoteAudioMixingStart params:@{
2321
                                                      @"message": @"RemoteAudioMixingStarted"
2440
                                                      @"message": @"RemoteAudioMixingStarted"
2341
                                            }];
2460
                                            }];
2342
 }
2461
 }
2343
 
2462
 
2463
+- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine rtmpStreamingChangedToState:(NSString *_Nonnull)url state:(AgoraRtmpStreamingState)state errorCode:(AgoraRtmpStreamingErrorCode)errorCode {
2464
+  [self sendEvent:AGRtmpStreamingStateChanged params:@{
2465
+                                                       @"url": url,
2466
+                                                       @"state": @(state),
2467
+                                                       @"errorCode": @(errorCode)
2468
+                                                       }];
2469
+}
2470
+
2344
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine streamUnpublishedWithUrl:(NSString *_Nonnull)url {
2471
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine streamUnpublishedWithUrl:(NSString *_Nonnull)url {
2345
   [self sendEvent:AGStreamUnpublish params:@{
2472
   [self sendEvent:AGStreamUnpublish params:@{
2346
                                            @"url": url,
2473
                                            @"url": url,
2353
                                               }];
2480
                                               }];
2354
 }
2481
 }
2355
 
2482
 
2483
+- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine localVideoStateChange:(AgoraLocalVideoStreamState)state error:(AgoraLocalVideoStreamError)error {
2484
+  [self sendEvent:AGLocalVideoChanged params:@{
2485
+                                               @"state": @(state),
2486
+                                               @"errorCode": @(error)
2487
+                                               }];
2488
+}
2489
+
2356
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine streamInjectedStatusOfUrl:(NSString *_Nonnull)url uid:(NSUInteger)uid status:(AgoraInjectStreamStatus)status {
2490
 - (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine streamInjectedStatusOfUrl:(NSString *_Nonnull)url uid:(NSUInteger)uid status:(AgoraInjectStreamStatus)status {
2357
   [self sendEvent:AGStreamInjectedStatus params:@{
2491
   [self sendEvent:AGStreamInjectedStatus params:@{
2358
                                                 @"uid": @(uid),
2492
                                                 @"uid": @(uid),

+ 56
- 0
lib/RtcEngine.native.d.ts View File

952
      * @returns Promise<{success, value}>
952
      * @returns Promise<{success, value}>
953
      */
953
      */
954
     static setCameraCapturerConfiguration(config: CameraCapturerConfiguration): Promise<any>;
954
     static setCameraCapturerConfiguration(config: CameraCapturerConfiguration): Promise<any>;
955
+    /**
956
+     * Gets the audio mixing volume for local playback.
957
+     *
958
+     * note:
959
+     * This method helps troubleshoot audio volume related issues.
960
+     *
961
+     * @returns Promise{<success, value}>
962
+     */
963
+    static getAudioMixingPlayoutVolume(): Promise<any>;
964
+    /**
965
+     * Gets the audio mixing volume for publishing.
966
+     *
967
+     * note:
968
+     * This method helps troubleshoot audio volume related issues.
969
+     *
970
+     * @returns Promise{<success, value}>
971
+     */
972
+    static getAudioMixingPublishVolume(): Promise<any>;
973
+    /**
974
+     * sendMediaData for media observer.
975
+     *
976
+     * note:
977
+     * This method needs you invoke registerMediaMetadataObserver success first and you could send media data through interval media observer feature.
978
+     * The data have limit length is 1024 bytes, if you pass data length bigger than limit it will failed.
979
+     * @param data String: 1024 bytes limit
980
+     * @returns Promise<{success}>
981
+     */
982
+    static sendMediaData(data: String): Promise<any>;
983
+    /**
984
+     * Registers the metadata observer.
985
+     *
986
+     * note:
987
+     * This method only work in live mode
988
+     * This method enables you to add synchronized metadata in the video stream for more diversified live broadcast interactions, such as sending shopping links, digital coupons, and online quizzes.
989
+     * This method trigger 'mediaMetaDataReceived' event, here is example:
990
+     * ```javascript
991
+     *      RtcEngine.on("mediaMetaDataReceived", (data) => {
992
+     *        console.log("mediaMetaDataReceived", data);
993
+     *      })
994
+     * ```
995
+     * @returns Promise{<success, value}>
996
+     */
997
+    static registerMediaMetadataObserver(): Promise<any>;
998
+    /**
999
+     * Get local device camera support info
1000
+     *
1001
+     * note:
1002
+     * This method returns your current device camera support info.
1003
+     * ```javascript
1004
+     *      RtcEngine.getCameraInfo().then(info => {
1005
+     *         console.log("your currrent camera", info);
1006
+     *      })
1007
+     * ```
1008
+     * @returns Promise{cameraSupportInfo}>
1009
+     */
1010
+    static getCameraInfo(): Promise<any>;
955
 }
1011
 }
956
 export default RtcEngine;
1012
 export default RtcEngine;

+ 82
- 0
lib/RtcEngine.native.js View File

1
 "use strict";
1
 "use strict";
2
 Object.defineProperty(exports, "__esModule", { value: true });
2
 Object.defineProperty(exports, "__esModule", { value: true });
3
+const tslib_1 = require("tslib");
3
 const react_native_1 = require("react-native");
4
 const react_native_1 = require("react-native");
4
 const { Agora } = react_native_1.NativeModules;
5
 const { Agora } = react_native_1.NativeModules;
5
 const AgoraEventEmitter = new react_native_1.NativeEventEmitter(Agora);
6
 const AgoraEventEmitter = new react_native_1.NativeEventEmitter(Agora);
1186
     static setCameraCapturerConfiguration(config) {
1187
     static setCameraCapturerConfiguration(config) {
1187
         return Agora.setCameraCapturerConfiguration(config);
1188
         return Agora.setCameraCapturerConfiguration(config);
1188
     }
1189
     }
1190
+    /**
1191
+     * Gets the audio mixing volume for local playback.
1192
+     *
1193
+     * note:
1194
+     * This method helps troubleshoot audio volume related issues.
1195
+     *
1196
+     * @returns Promise{<success, value}>
1197
+     */
1198
+    static getAudioMixingPlayoutVolume() {
1199
+        return Agora.getAudioMixingPlayoutVolume();
1200
+    }
1201
+    /**
1202
+     * Gets the audio mixing volume for publishing.
1203
+     *
1204
+     * note:
1205
+     * This method helps troubleshoot audio volume related issues.
1206
+     *
1207
+     * @returns Promise{<success, value}>
1208
+     */
1209
+    static getAudioMixingPublishVolume() {
1210
+        return Agora.getAudioMixingPublishVolume();
1211
+    }
1212
+    /**
1213
+     * sendMediaData for media observer.
1214
+     *
1215
+     * note:
1216
+     * This method needs you invoke registerMediaMetadataObserver success first and you could send media data through interval media observer feature.
1217
+     * The data have limit length is 1024 bytes, if you pass data length bigger than limit it will failed.
1218
+     * @param data String: 1024 bytes limit
1219
+     * @returns Promise<{success}>
1220
+     */
1221
+    static sendMediaData(data) {
1222
+        return Agora.sendMediaData(data);
1223
+    }
1224
+    /**
1225
+     * Registers the metadata observer.
1226
+     *
1227
+     * note:
1228
+     * This method only work in live mode
1229
+     * This method enables you to add synchronized metadata in the video stream for more diversified live broadcast interactions, such as sending shopping links, digital coupons, and online quizzes.
1230
+     * This method trigger 'mediaMetaDataReceived' event, here is example:
1231
+     * ```javascript
1232
+     *      RtcEngine.on("mediaMetaDataReceived", (data) => {
1233
+     *        console.log("mediaMetaDataReceived", data);
1234
+     *      })
1235
+     * ```
1236
+     * @returns Promise{<success, value}>
1237
+     */
1238
+    static registerMediaMetadataObserver() {
1239
+        return Agora.registerMediaMetadataObserver();
1240
+    }
1241
+    /**
1242
+     * Get local device camera support info
1243
+     *
1244
+     * note:
1245
+     * This method returns your current device camera support info.
1246
+     * ```javascript
1247
+     *      RtcEngine.getCameraInfo().then(info => {
1248
+     *         console.log("your currrent camera", info);
1249
+     *      })
1250
+     * ```
1251
+     * @returns Promise{cameraSupportInfo}>
1252
+     */
1253
+    static getCameraInfo() {
1254
+        return tslib_1.__awaiter(this, void 0, void 0, function* () {
1255
+            let zoomSupported = yield this.isCameraZoomSupported();
1256
+            let torchSupported = yield this.isCameraTorchSupported();
1257
+            let focusSupported = yield this.isCameraFocusSupported();
1258
+            let exposurePositionSupported = yield this.isCameraExposurePositionSupported();
1259
+            let autoFocusFaceModeSupported = yield this.isCameraAutoFocusFaceModeSupported();
1260
+            let maxZoomFactor = yield this.getCameraMaxZoomFactor();
1261
+            return {
1262
+                zoomSupported,
1263
+                torchSupported,
1264
+                focusSupported,
1265
+                exposurePositionSupported,
1266
+                autoFocusFaceModeSupported,
1267
+                maxZoomFactor
1268
+            };
1269
+        });
1270
+    }
1189
 }
1271
 }
1190
 RtcEngine.eventTypes = new Set();
1272
 RtcEngine.eventTypes = new Set();
1191
 exports.default = RtcEngine;
1273
 exports.default = RtcEngine;

+ 1
- 1
lib/RtcEngine.native.js.map
File diff suppressed because it is too large
View File


+ 1
- 1
package.json View File

1
 {
1
 {
2
   "name": "react-native-agora",
2
   "name": "react-native-agora",
3
-  "version": "2.4.0-alpha.5",
3
+  "version": "2.4.1-alpha.1",
4
   "description": "React Native around the Agora RTC SDKs for Android and iOS agora",
4
   "description": "React Native around the Agora RTC SDKs for Android and iOS agora",
5
   "summary": "agora native sdk for react-native",
5
   "summary": "agora native sdk for react-native",
6
   "main": "lib/index.js",
6
   "main": "lib/index.js",

+ 1
- 1
react-native-agora.podspec View File

93
       "$(SDKROOT)../../ios/Pods"
93
       "$(SDKROOT)../../ios/Pods"
94
     ]
94
     ]
95
   }
95
   }
96
-  s.dependency "AgoraRtcEngine_iOS", "2.4.0.1"
96
+  s.dependency "AgoraRtcEngine_iOS", "2.4.1"
97
   s.dependency 'React'
97
   s.dependency 'React'
98
 
98
 
99
 end
99
 end

+ 85
- 0
src/RtcEngine.native.ts View File

1336
     static setCameraCapturerConfiguration(config: CameraCapturerConfiguration): Promise<any> {
1336
     static setCameraCapturerConfiguration(config: CameraCapturerConfiguration): Promise<any> {
1337
         return Agora.setCameraCapturerConfiguration(config);
1337
         return Agora.setCameraCapturerConfiguration(config);
1338
     }
1338
     }
1339
+
1340
+    /**
1341
+     * Gets the audio mixing volume for local playback.
1342
+     * 
1343
+     * note:
1344
+     * This method helps troubleshoot audio volume related issues.
1345
+     * 
1346
+     * @returns Promise{<success, value}>
1347
+     */
1348
+    static getAudioMixingPlayoutVolume(): Promise<any> {
1349
+        return Agora.getAudioMixingPlayoutVolume();
1350
+    }
1351
+
1352
+    /**
1353
+     * Gets the audio mixing volume for publishing.
1354
+     * 
1355
+     * note:
1356
+     * This method helps troubleshoot audio volume related issues.
1357
+     * 
1358
+     * @returns Promise{<success, value}>
1359
+     */
1360
+    static getAudioMixingPublishVolume(): Promise<any> {
1361
+        return Agora.getAudioMixingPublishVolume();
1362
+    }
1363
+
1364
+    /**
1365
+     * sendMediaData for media observer.
1366
+     * 
1367
+     * note:
1368
+     * This method needs you invoke registerMediaMetadataObserver success first and you could send media data through interval media observer feature.
1369
+     * The data have limit length is 1024 bytes, if you pass data length bigger than limit it will failed.
1370
+     * @param data String: 1024 bytes limit
1371
+     * @returns Promise<{success}>
1372
+     */
1373
+    static sendMediaData(data: String): Promise<any> {
1374
+        return Agora.sendMediaData(data);
1375
+    }
1376
+
1377
+    /**
1378
+     * Registers the metadata observer.
1379
+     * 
1380
+     * note:
1381
+     * This method only work in live mode
1382
+     * This method enables you to add synchronized metadata in the video stream for more diversified live broadcast interactions, such as sending shopping links, digital coupons, and online quizzes.
1383
+     * This method trigger 'mediaMetaDataReceived' event, here is example:
1384
+     * ```javascript
1385
+     *      RtcEngine.on("mediaMetaDataReceived", (data) => {
1386
+     *        console.log("mediaMetaDataReceived", data);
1387
+     *      })
1388
+     * ```
1389
+     * @returns Promise{<success, value}>
1390
+     */
1391
+    static registerMediaMetadataObserver(): Promise<any> {
1392
+        return Agora.registerMediaMetadataObserver();
1393
+    }
1394
+
1395
+    /**
1396
+     * Get local device camera support info
1397
+     * 
1398
+     * note:
1399
+     * This method returns your current device camera support info.
1400
+     * ```javascript
1401
+     *      RtcEngine.getCameraInfo().then(info => {
1402
+     *         console.log("your currrent camera", info);
1403
+     *      })
1404
+     * ```
1405
+     * @returns Promise{cameraSupportInfo}>
1406
+     */
1407
+    static async getCameraInfo(): Promise<any> {
1408
+        let zoomSupported = await this.isCameraZoomSupported();
1409
+        let torchSupported = await this.isCameraTorchSupported();
1410
+        let focusSupported = await this.isCameraFocusSupported();
1411
+        let exposurePositionSupported = await this.isCameraExposurePositionSupported();
1412
+        let autoFocusFaceModeSupported = await this.isCameraAutoFocusFaceModeSupported();
1413
+        let maxZoomFactor = await this.getCameraMaxZoomFactor();
1414
+        return {
1415
+            zoomSupported,
1416
+            torchSupported,
1417
+            focusSupported,
1418
+            exposurePositionSupported,
1419
+            autoFocusFaceModeSupported,
1420
+            maxZoomFactor
1421
+        }
1422
+    }
1423
+
1339
 }
1424
 }
1340
 
1425
 
1341
 
1426