diff --git a/.github/ci/build/build_ios.sh b/.github/ci/build/build_ios.sh
index 6cfc26eb0..619315616 100644
--- a/.github/ci/build/build_ios.sh
+++ b/.github/ci/build/build_ios.sh
@@ -53,6 +53,11 @@ echo short_version: $short_version
echo pwd: `pwd`
echo sdk_url: $sdk_url
+export https_proxy=10.10.114.55:1080
+export http_proxy=10.10.114.55:1080
+export all_proxy=10.10.114.55:1080
+export LANG=en_US.UTF-8
+
unzip_name=Agora_Native_SDK_for_iOS_FULL
zip_name=output.zip
sdk_url_flag=false
diff --git a/.github/ci/build/build_mac.sh b/.github/ci/build/build_mac.sh
index e0d163db8..5c48c25f3 100644
--- a/.github/ci/build/build_mac.sh
+++ b/.github/ci/build/build_mac.sh
@@ -51,6 +51,11 @@ echo short_version: $short_version
echo pwd: `pwd`
echo sdk_url: $sdk_url
+export https_proxy=10.10.114.55:1080
+export http_proxy=10.10.114.55:1080
+export all_proxy=10.10.114.55:1080
+export LANG=en_US.UTF-8
+
unzip_name=Agora_Native_SDK_for_iOS_FULL
zip_name=output.zip
sdk_url_flag=false
@@ -60,7 +65,7 @@ if [ -z "$sdk_url" ]; then
sdk_url_flag=false
echo "sdk_url is empty"
echo unzip_name: $unzip_name
- mkdir ./$unzip_name/samples
+ mkdir -p ./$unzip_name/samples
cp -rf ./macOS ./$unzip_name/samples/APIExample || exit 1
ls -al ./$unzip_name/samples/API-Example/
else
diff --git a/.gitignore b/.gitignore
index b27e7ef9b..606b91bdf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ xcuserdata
.DS_Store
AgoraRtcKit.framework
*/libs
+/sdk
diff --git a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java
index b9c7b0001..fa2112fe8 100644
--- a/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java
+++ b/Android/APIExample-Audio/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java
@@ -328,7 +328,7 @@ public boolean onEarMonitoringAudioFrame(int type, int samplesPerChannel, int by
}
@Override
- public boolean onPlaybackAudioFrameBeforeMixing(String channelId, int uid, int type, int samplesPerChannel, int bytesPerSample, int channels, int samplesPerSec, ByteBuffer buffer, long renderTimeMs, int avsync_type, int rtpTimestamp) {
+ public boolean onPlaybackAudioFrameBeforeMixing(String channelId, int uid, int type, int samplesPerChannel, int bytesPerSample, int channels, int samplesPerSec, ByteBuffer buffer, long renderTimeMs, int avsync_type, int rtpTimestamp, long presentationMs) {
return false;
}
diff --git a/Android/APIExample-Audio/gradle.properties b/Android/APIExample-Audio/gradle.properties
index ae0306701..7c1f8e00f 100644
--- a/Android/APIExample-Audio/gradle.properties
+++ b/Android/APIExample-Audio/gradle.properties
@@ -21,4 +21,4 @@ android.enableJetifier=true
# read enable simple filter section on README first before set this flag to TRUE
simpleFilter = false
-rtc_sdk_version = 4.5.0
\ No newline at end of file
+rtc_sdk_version = 4.5.1
\ No newline at end of file
diff --git a/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/OriginAudioData.kt b/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/OriginAudioData.kt
index dce16b412..b67566201 100644
--- a/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/OriginAudioData.kt
+++ b/Android/APIExample-Compose/app/src/main/java/io/agora/api/example/compose/samples/OriginAudioData.kt
@@ -354,7 +354,8 @@ private class OriginAudioDataRewriter(
buffer: ByteBuffer?,
renderTimeMs: Long,
avsync_type: Int,
- rtpTimestamp: Int
+ rtpTimestamp: Int,
+ presentationMs: Long
) = false
override fun getObservedAudioFramePosition() =
diff --git a/Android/APIExample-Compose/gradle.properties b/Android/APIExample-Compose/gradle.properties
index 58fe9e1a3..b50d3a2b9 100644
--- a/Android/APIExample-Compose/gradle.properties
+++ b/Android/APIExample-Compose/gradle.properties
@@ -22,4 +22,4 @@ kotlin.code.style=official
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
-rtc_sdk_version = 4.5.0
\ No newline at end of file
+rtc_sdk_version = 4.5.1
\ No newline at end of file
diff --git a/Android/APIExample-Compose/gradle/libs.versions.toml b/Android/APIExample-Compose/gradle/libs.versions.toml
index 0a90ebb75..a80f21448 100644
--- a/Android/APIExample-Compose/gradle/libs.versions.toml
+++ b/Android/APIExample-Compose/gradle/libs.versions.toml
@@ -12,7 +12,7 @@ composeBom = "2023.08.00"
loggingInterceptor = "4.10.0"
materialIconsExtended = "1.6.0"
navigationCompose = "2.7.7"
-#agoraSdk = "4.5.0"
+#agoraSdk = "4.5.1"
okhttp = "4.10.0"
[libraries]
diff --git a/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h b/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h
index c3bfa34cb..9f106238d 100644
--- a/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h
+++ b/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/AgoraBase.h
@@ -427,6 +427,10 @@ enum WARN_CODE_TYPE {
* 1053: Audio Device Module: The settings are improper.
*/
WARN_ADM_IMPROPER_SETTINGS = 1053,
+ /**
+ * 1055: Audio Device Module: The audio device is in a pop state.
+ */
+ WARN_ADM_POP_STATE = 1055,
/**
* 1322: No recording device.
*/
@@ -2701,9 +2705,17 @@ enum AUDIO_SCENARIO_TYPE {
*/
AUDIO_SCENARIO_MEETING = 8,
/**
- * 9: The number of enumerations.
+ * 9: AI Server.
+ */
+ AUDIO_SCENARIO_AI_SERVER = 9,
+ /**
+ * 10: AI Client.
+ */
+ AUDIO_SCENARIO_AI_CLIENT = 10,
+ /**
+ * 11: The number of enumerations.
*/
- AUDIO_SCENARIO_NUM = 9,
+ AUDIO_SCENARIO_NUM = 11,
};
/**
diff --git a/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/NGIAgoraLocalUser.h b/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/NGIAgoraLocalUser.h
index debc52706..86b423b76 100644
--- a/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/NGIAgoraLocalUser.h
+++ b/Android/APIExample/agora-simple-filter/src/main/cpp/AgoraRtcKit/NGIAgoraLocalUser.h
@@ -1577,7 +1577,7 @@ class ILocalUserObserver {
/**
* datastream from this connection.
*/
- virtual void onStreamMessage(user_id_t userId, int streamId, const char* data, size_t length) {}
+ virtual void onStreamMessage(user_id_t userId, int streamId, const char* data, size_t length, uint64_t sendTs = 0) {}
/**
* Occurs when the remote user state is updated.
diff --git a/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h b/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h
index c3bfa34cb..9f106238d 100644
--- a/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h
+++ b/Android/APIExample/agora-stream-encrypt/src/main/cpp/include/agora/AgoraBase.h
@@ -427,6 +427,10 @@ enum WARN_CODE_TYPE {
* 1053: Audio Device Module: The settings are improper.
*/
WARN_ADM_IMPROPER_SETTINGS = 1053,
+ /**
+ * 1055: Audio Device Module: The audio device is in a pop state.
+ */
+ WARN_ADM_POP_STATE = 1055,
/**
* 1322: No recording device.
*/
@@ -2701,9 +2705,17 @@ enum AUDIO_SCENARIO_TYPE {
*/
AUDIO_SCENARIO_MEETING = 8,
/**
- * 9: The number of enumerations.
+ * 9: AI Server.
+ */
+ AUDIO_SCENARIO_AI_SERVER = 9,
+ /**
+ * 10: AI Client.
+ */
+ AUDIO_SCENARIO_AI_CLIENT = 10,
+ /**
+ * 11: The number of enumerations.
*/
- AUDIO_SCENARIO_NUM = 9,
+ AUDIO_SCENARIO_NUM = 11,
};
/**
diff --git a/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/PictureInPicture.java b/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/PictureInPicture.java
index 4c21e0082..87913abe3 100644
--- a/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/PictureInPicture.java
+++ b/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/PictureInPicture.java
@@ -210,6 +210,10 @@ public void onPermissionsResult(boolean allPermissionsGranted, String[] permissi
fl_remote3.removeAllViews();
}
} else if (v.getId() == switch_float_window.getId()) {
+ if (Build.VERSION.SDK_INT >= 26 && requireActivity().isInPictureInPictureMode()) {
+ showLongToast("Please exit Picture-in-Picture mode first");
+ return;
+ }
showFloatWindow();
} else if (v.getId() == R.id.btn_pip) {
if (checkPipSupported()) {
@@ -500,7 +504,7 @@ private VideoReportLayout getRemoteView(int uid) {
private void showFloatWindow() {
FragmentActivity context = requireActivity();
if (FloatWindowHelper.checkPermission(context)) {
- if (isFloatWindowShowing()) {
+ if (isFloatWindowShowing() || (Build.VERSION.SDK_INT >= 26 && requireActivity().isInPictureInPictureMode())) {
return;
}
floatWindowView = FloatWindowHelper.createFloatView(context, 50, 50);
@@ -563,6 +567,11 @@ private void enterPip() {
if (android.os.Build.VERSION.SDK_INT < 26) {
return;
}
+
+ if(isFloatWindowShowing()) {
+ dismissFloatWindow();
+ }
+
requireActivity().enterPictureInPictureMode(pictureInPictureParamsBuilder
.setAspectRatio(new Rational(video_layout_container.getWidth(), video_layout_container.getHeight()))
.build());
diff --git a/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java b/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java
index ec4d0dd86..c71801453 100644
--- a/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java
+++ b/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ProcessAudioRawData.java
@@ -340,7 +340,7 @@ public boolean onEarMonitoringAudioFrame(int type, int samplesPerChannel, int by
}
@Override
- public boolean onPlaybackAudioFrameBeforeMixing(String channelId, int uid, int type, int samplesPerChannel, int bytesPerSample, int channels, int samplesPerSec, ByteBuffer buffer, long renderTimeMs, int avsync_type, int rtpTimestamp) {
+ public boolean onPlaybackAudioFrameBeforeMixing(String channelId, int uid, int type, int samplesPerChannel, int bytesPerSample, int channels, int samplesPerSec, ByteBuffer buffer, long renderTimeMs, int avsync_type, int rtpTimestamp, long presentationMs) {
return false;
}
diff --git a/Android/APIExample/gradle.properties b/Android/APIExample/gradle.properties
index 903fe7611..3b22c9c75 100644
--- a/Android/APIExample/gradle.properties
+++ b/Android/APIExample/gradle.properties
@@ -23,4 +23,4 @@ simpleFilter = false
# read enable stream encrypt section on README first before set this flag to TRUE
streamEncrypt = false
-rtc_sdk_version = 4.5.0
+rtc_sdk_version = 4.5.1
diff --git a/iOS/APIExample-Audio/Podfile b/iOS/APIExample-Audio/Podfile
index 5f8a873f1..0e9cc76be 100644
--- a/iOS/APIExample-Audio/Podfile
+++ b/iOS/APIExample-Audio/Podfile
@@ -7,10 +7,10 @@ target 'APIExample-Audio' do
pod 'Floaty', '~> 4.2.0'
pod 'AGEVideoLayout', '~> 1.0.2'
- pod 'AgoraAudio_iOS', '4.5.0'
+ pod 'AgoraAudio_iOS', '4.5.1'
# pod 'sdk', :path => 'sdk.podspec'
end
pre_install do |installer|
- # system("sh .download_script.sh 4.5.0 true")
+ # system("sh .download_script.sh 4.5.1 true")
end
diff --git a/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/CustomAudioRender/CustomAudioRender.m b/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/CustomAudioRender/CustomAudioRender.m
index 85989534d..8264d3f13 100644
--- a/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/CustomAudioRender/CustomAudioRender.m
+++ b/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/CustomAudioRender/CustomAudioRender.m
@@ -94,7 +94,8 @@ - (void)viewDidLoad {
NSString *channelName = [self.configs objectForKey:@"channelName"];
// enable video module and set up video encoding configs
[self.agoraKit enableAudio];
-
+ [self.agoraKit setAudioScenario:AgoraAudioScenarioGameStreaming];
+
// set up local video to render your local camera preview
AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
videoCanvas.uid = 0;
@@ -113,7 +114,7 @@ - (void)viewDidLoad {
// when joining channel. The channel name and uid used to calculate
// the token has to match the ones used for channel join
AgoraRtcChannelMediaOptions *options = [[AgoraRtcChannelMediaOptions alloc] init];
- options.publishMicrophoneTrack = NO;
+ options.publishMicrophoneTrack = YES;
options.publishCameraTrack = NO;
options.autoSubscribeAudio = YES;
options.autoSubscribeVideo = NO;
diff --git a/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/StreamEncryption/StreamEncryption.m b/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/StreamEncryption/StreamEncryption.m
index 4d880ca67..4b2df6ce2 100644
--- a/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/StreamEncryption/StreamEncryption.m
+++ b/iOS/APIExample-OC/APIExample-OC/Examples/Advanced/StreamEncryption/StreamEncryption.m
@@ -116,7 +116,7 @@ - (void)viewDidLoad {
NSString *channelName = [self.configs objectForKey:@"channelName"];
NSString *secret = [self.configs objectForKey:@"secret"];
AgoraEncryptionMode mode = ((NSNumber *)[self.configs objectForKey:@"mode"]).integerValue;
- BOOL useCustom = ((NSNumber *)[self.configs objectForKey:@"useCustom"]).boolValue;
+ BOOL useCustom = ((NSNumber *)[self.configs objectForKey:@"userCustom"]).boolValue;
// make myself a broadcaster
[self.agoraKit setClientRole:(AgoraClientRoleBroadcaster)];
// enable video module and set up video encoding configs
diff --git a/iOS/APIExample-OC/Podfile b/iOS/APIExample-OC/Podfile
index 8bdb605ed..29e36733d 100644
--- a/iOS/APIExample-OC/Podfile
+++ b/iOS/APIExample-OC/Podfile
@@ -2,7 +2,7 @@
# platform :ios, '9.0'
def common_pods
- pod 'AgoraRtcEngine_iOS', '4.5.0'
+ pod 'AgoraRtcEngine_iOS', '4.5.1'
# pod 'sdk', :path => 'sdk.podspec'
end
@@ -26,5 +26,5 @@ target 'SimpleFilter' do
end
pre_install do |installer|
- # system("sh .download_script.sh 4.5.0 true")
+ # system("sh .download_script.sh 4.5.1 true")
end
diff --git a/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/CustomRender/CustomRenderExample.swift b/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/CustomRender/CustomRenderExample.swift
index 29f2aa4ba..1663b9b0d 100644
--- a/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/CustomRender/CustomRenderExample.swift
+++ b/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/CustomRender/CustomRenderExample.swift
@@ -49,7 +49,7 @@ struct CustomRenderExample: View {
VStack(spacing: 30) {
PIPDisplayView(viewModel: pipViewModel)
.frame(maxWidth: .infinity, maxHeight: 200)
-
+
Button {
pipViewModel.togglePiP()
} label: {
@@ -78,7 +78,6 @@ struct CustomRenderExample: View {
customRenderViewModel.cleanRtc()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
- .adaptiveBackground(Color.orange)
}
}
diff --git a/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/PIPCommon/PIPDisplayView.swift b/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/PIPCommon/PIPDisplayView.swift
index a0782f96b..7ad1f0147 100644
--- a/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/PIPCommon/PIPDisplayView.swift
+++ b/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/PIPCommon/PIPDisplayView.swift
@@ -100,7 +100,14 @@ extension PIPViewModel: AVPictureInPictureControllerDelegate {
guard let vc = pictureInPictureController.contentSource?.activeVideoCallContentViewController, let pipSourceView = backgroundView.pipSourceView else { return }
vc.view.addSubview(pipSourceView)
- pipSourceView.frame = vc.view.bounds
+ pipSourceView.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ pipSourceView.leadingAnchor.constraint(equalTo: vc.view.leadingAnchor),
+ pipSourceView.trailingAnchor.constraint(equalTo: vc.view.trailingAnchor),
+ pipSourceView.topAnchor.constraint(equalTo: vc.view.topAnchor),
+ pipSourceView.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor)
+ ])
+ vc.view.layoutIfNeeded()
}
func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
@@ -108,6 +115,9 @@ extension PIPViewModel: AVPictureInPictureControllerDelegate {
pipSourceView.removeFromSuperview()
backgroundView.addSubview(pipSourceView)
+ pipSourceView.frame = backgroundView.bounds
+ pipSourceView.setNeedsLayout()
+ pipSourceView.layoutIfNeeded()
}
}
diff --git a/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/SDKRender/SDKRenderExample.swift b/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/SDKRender/SDKRenderExample.swift
index 2e35b343e..64641b951 100644
--- a/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/SDKRender/SDKRenderExample.swift
+++ b/iOS/APIExample-SwiftUI/APIExample-SwiftUI/Examples/Advanced/PictureInPicture/SDKRender/SDKRenderExample.swift
@@ -13,7 +13,7 @@ struct SDKRenderMockContainerView: View {
var body: some View {
HStack {
- localView.frame(maxWidth: 200)
+ localView
ForEach(viewModel.remoteRenderViews) { view in
view
}
@@ -77,7 +77,6 @@ struct SDKRenderExample: View {
sdkRenderViewModel.cleanRtc()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
- .adaptiveBackground(Color.orange)
}
}
diff --git a/iOS/APIExample-SwiftUI/Podfile b/iOS/APIExample-SwiftUI/Podfile
index 60484cca8..f7f1d4320 100644
--- a/iOS/APIExample-SwiftUI/Podfile
+++ b/iOS/APIExample-SwiftUI/Podfile
@@ -2,7 +2,7 @@
# platform :ios, '9.0'
def common_pods
- pod 'AgoraRtcEngine_iOS', '4.5.0'
+ pod 'AgoraRtcEngine_iOS', '4.5.1'
# pod 'sdk', :path => 'sdk.podspec'
end
@@ -33,5 +33,5 @@ end
#end
pre_install do |installer|
-# system("sh .download_script.sh 4.5.0 true")
+# system("sh .download_script.sh 4.5.1 true")
end
diff --git a/iOS/APIExample/APIExample/Examples/Advanced/LiveStreaming/Base.lproj/LiveStreaming.storyboard b/iOS/APIExample/APIExample/Examples/Advanced/LiveStreaming/Base.lproj/LiveStreaming.storyboard
index d433b379b..e70aad271 100644
--- a/iOS/APIExample/APIExample/Examples/Advanced/LiveStreaming/Base.lproj/LiveStreaming.storyboard
+++ b/iOS/APIExample/APIExample/Examples/Advanced/LiveStreaming/Base.lproj/LiveStreaming.storyboard
@@ -42,7 +42,7 @@