diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d2b16396..2b340a74c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+## [3.1.5](https://github.com/AgoraIO-Community/react-native-agora/compare/v3.1.4...v3.1.5) (2020-12-15)
+
+
+### Bug Fixes
+
+* `RtcSurfaceView` memory leak ([c8845fe](https://github.com/AgoraIO-Community/react-native-agora/commit/c8845fe04c1596fe2e7242302bf160bc671910cb))
+
+
+### Features
+
+* example support `switchRender` ([a6a509e](https://github.com/AgoraIO-Community/react-native-agora/commit/a6a509e273f64c67dce67fc61a9451d5b0ffeb70)), closes [#309](https://github.com/AgoraIO-Community/react-native-agora/issues/309)
+
## [3.1.4](https://github.com/AgoraIO-Community/react-native-agora/compare/v3.1.4-rc.1...v3.1.4) (2020-12-02)
diff --git a/example/ios/AgoraExample/Info.plist b/example/ios/AgoraExample/Info.plist
index 41790beb9..7361dfb89 100644
--- a/example/ios/AgoraExample/Info.plist
+++ b/example/ios/AgoraExample/Info.plist
@@ -37,8 +37,12 @@
+ NSCameraUsageDescription
+ Camera
NSLocationWhenInUseUsageDescription
+ NSMicrophoneUsageDescription
+ Microphone
UILaunchStoryboardName
LaunchScreen
UIRequiredDeviceCapabilities
diff --git a/example/src/examples/basic/JoinChannelVideo.tsx b/example/src/examples/basic/JoinChannelVideo.tsx
index b045dd917..d3af02635 100644
--- a/example/src/examples/basic/JoinChannelVideo.tsx
+++ b/example/src/examples/basic/JoinChannelVideo.tsx
@@ -1,18 +1,19 @@
import React, { Component } from 'react';
import {
- View,
- TextInput,
- PermissionsAndroid,
- StyleSheet,
Button,
+ PermissionsAndroid,
Platform,
+ StyleSheet,
+ TextInput,
+ TouchableOpacity,
+ View,
} from 'react-native';
import RtcEngine, {
- RtcLocalView,
- RtcRemoteView,
ChannelProfile,
ClientRole,
+ RtcLocalView,
+ RtcRemoteView,
} from 'react-native-agora';
const config = require('../../../agora.config.json');
@@ -22,6 +23,7 @@ interface State {
isJoined: boolean;
remoteUid: number | undefined;
switchCamera: boolean;
+ switchRender: boolean;
}
export default class JoinChannelAudio extends Component<{}, State, any> {
@@ -33,7 +35,8 @@ export default class JoinChannelAudio extends Component<{}, State, any> {
channelId: config.channelId,
isJoined: false,
remoteUid: undefined,
- switchCamera: false,
+ switchCamera: true,
+ switchRender: true,
};
}
@@ -107,6 +110,11 @@ export default class JoinChannelAudio extends Component<{}, State, any> {
});
};
+ _switchRender = () => {
+ const { switchRender } = this.state;
+ this.setState({ switchRender: !switchRender });
+ };
+
render() {
const { channelId, isJoined, switchCamera } = this.state;
return (
@@ -135,17 +143,31 @@ export default class JoinChannelAudio extends Component<{}, State, any> {
}
_renderVideo = () => {
- const { remoteUid } = this.state;
+ const { remoteUid, switchRender } = this.state;
return (
-
- {remoteUid !== undefined && (
+ {switchRender ? (
+
+ ) : (
)}
+ {remoteUid !== undefined && (
+
+ {switchRender ? (
+
+ ) : (
+
+ )}
+
+ )}
);
};
diff --git a/ios/RCTAgora/Base/.gitignore b/ios/RCTAgora/Base/.gitignore
new file mode 100644
index 000000000..9f11b755a
--- /dev/null
+++ b/ios/RCTAgora/Base/.gitignore
@@ -0,0 +1 @@
+.idea/
diff --git a/ios/RCTAgora/Base/RtcSurfaceView.swift b/ios/RCTAgora/Base/RtcSurfaceView.swift
index 2d20efc0c..e5181ec90 100644
--- a/ios/RCTAgora/Base/RtcSurfaceView.swift
+++ b/ios/RCTAgora/Base/RtcSurfaceView.swift
@@ -18,13 +18,17 @@ class RtcSurfaceView: UIView {
}()
private weak var channel: AgoraRtcChannel?
+ func destroy() {
+ canvas.view = nil
+ }
+
func setData(_ engine: AgoraRtcEngineKit, _ channel: AgoraRtcChannel?, _ uid: Int) {
self.channel = channel
canvas.channelId = channel?.getId()
canvas.uid = UInt(uid)
setupVideoCanvas(engine)
}
-
+
func resetVideoCanvas(_ engine: AgoraRtcEngineKit) {
let canvas = AgoraRtcVideoCanvas()
canvas.view = nil
@@ -32,14 +36,14 @@ class RtcSurfaceView: UIView {
canvas.channelId = self.canvas.channelId
canvas.uid = self.canvas.uid
canvas.mirrorMode = self.canvas.mirrorMode
-
+
if canvas.uid == 0 {
engine.setupLocalVideo(canvas)
} else {
engine.setupRemoteVideo(canvas)
}
}
-
+
private func setupVideoCanvas(_ engine: AgoraRtcEngineKit) {
if canvas.uid == 0 {
engine.setupLocalVideo(canvas)
@@ -47,7 +51,7 @@ class RtcSurfaceView: UIView {
engine.setupRemoteVideo(canvas)
}
}
-
+
func setRenderMode(_ engine: AgoraRtcEngineKit, _ renderMode: Int) {
canvas.renderMode = AgoraVideoRenderMode(rawValue: UInt(renderMode))!
setupRenderMode(engine)
diff --git a/ios/RCTAgora/React/RCTAgoraRtcSurfaceViewManager.swift b/ios/RCTAgora/React/RCTAgoraRtcSurfaceViewManager.swift
index 3a9c5bf69..66dd93179 100644
--- a/ios/RCTAgora/React/RCTAgoraRtcSurfaceViewManager.swift
+++ b/ios/RCTAgora/React/RCTAgoraRtcSurfaceViewManager.swift
@@ -9,6 +9,22 @@
import Foundation
import AgoraRtcKit
+fileprivate struct AssociatedKeys {
+ static var view: UInt8 = 0
+}
+
+@objc(AgoraRtcVideoCanvas)
+public extension AgoraRtcVideoCanvas {
+ @objc weak var view: UIView? {
+ get {
+ return objc_getAssociatedObject(self, &AssociatedKeys.view) as? UIView
+ }
+ set {
+ objc_setAssociatedObject(self, &AssociatedKeys.view, newValue, .OBJC_ASSOCIATION_ASSIGN)
+ }
+ }
+}
+
@objc(RCTAgoraRtcSurfaceViewManager)
class RCTAgoraRtcSurfaceViewManager: RCTViewManager {
override func view() -> UIView! {
@@ -39,8 +55,9 @@ class RCTAgoraRtcSurfaceViewManager: RCTViewManager {
class RtcView: RtcSurfaceView {
private var getEngine: (() -> AgoraRtcEngineKit?)?
private var getChannel: ((_ channelId: String) -> AgoraRtcChannel?)?
-
+
deinit {
+ destroy()
// if let engine = getEngine?() {
// resetVideoCanvas(engine)
// }
diff --git a/package.json b/package.json
index 5ca3ad99f..3f7fd4824 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-agora",
- "version": "3.1.4",
+ "version": "3.1.5",
"description": "Agora RTC SDK For React Native",
"main": "lib/commonjs/index",
"module": "lib/module/index",