11package io .agora .rtc .ng .react ;
22
3+ import android .app .Activity ;
34import android .util .Base64 ;
5+ import android .graphics .Rect ;
6+ import android .os .Build ;
7+ import android .util .Rational ;
48
59import androidx .annotation .NonNull ;
610
2024
2125import java .util .ArrayList ;
2226import java .util .List ;
27+ import java .util .Map ;
2328
2429import io .agora .iris .IrisApiEngine ;
2530import io .agora .iris .IrisEventHandler ;
2631
32+ import io .agora .iris .pip .AgoraPIPActivityProxy ;
33+ import io .agora .iris .pip .AgoraPIPController ;
34+
2735@ ReactModule (name = AgoraRtcNgModule .NAME )
2836public class AgoraRtcNgModule extends AgoraRtcNgSpec implements IrisEventHandler {
2937 public static final String NAME = "AgoraRtcNg" ;
3038 public final Object irisApiLock = new Object ();
3139 public IrisApiEngine irisApiEngine ;
40+ private AgoraPIPController pipController ;
3241
3342 AgoraRtcNgModule (ReactApplicationContext context ) {
3443 super (context );
@@ -47,6 +56,10 @@ public boolean newIrisApiEngine() {
4756 IrisApiEngine .enableUseJsonArray (true );
4857 irisApiEngine = new IrisApiEngine (getReactApplicationContext ());
4958 irisApiEngine .setEventHandler (this );
59+ Activity currentActivity = getReactApplicationContext ().getCurrentActivity ();
60+ if (currentActivity != null ) {
61+ initPipController (currentActivity );
62+ }
5063 return true ;
5164 }
5265 }
@@ -60,6 +73,7 @@ public boolean destroyIrisApiEngine() {
6073 irisApiEngine .setEventHandler (null );
6174 irisApiEngine .destroy ();
6275 irisApiEngine = null ;
76+ pipController = null ;
6377 return true ;
6478 }
6579 }
@@ -95,6 +109,34 @@ public String callApi(ReadableMap args) {
95109 }
96110 }
97111
112+ private void initPipController (@ NonNull Activity activity ) {
113+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
114+
115+ if (!(activity instanceof AgoraPIPActivityProxy )) {
116+ return ;
117+ }
118+
119+ if (pipController != null ) {
120+ pipController .dispose ();
121+ }
122+
123+ pipController = new AgoraPIPController (
124+ (AgoraPIPActivityProxy ) activity ,
125+ new AgoraPIPController .PIPStateChangedListener () {
126+ @ Override
127+ public void onPIPStateChangedListener (
128+ AgoraPIPController .PIPState state , String error ) {
129+ try {
130+ OnEvent ("AgoraPip_onPipStateChanged" ,
131+ new JSONObject ().put ("state" , state .getValue ()).put ("error" , error ).toString (), null );
132+ } catch (JSONException e ) {
133+ throw new RuntimeException (e );
134+ }
135+ }
136+ });
137+ }
138+ }
139+
98140 @ ReactMethod
99141 public void showRPSystemBroadcastPickerView (boolean showsMicrophoneButton , Promise promise ) {
100142 promise .reject ("" , "not support" );
@@ -110,6 +152,112 @@ public void removeListeners(double count) {
110152
111153 }
112154
155+ private boolean checkPipIsReady () {
156+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .O ) {
157+ return false ;
158+ }
159+ if (pipController == null ) {
160+ return false ;
161+ }
162+ return true ;
163+ }
164+
165+ @ ReactMethod (isBlockingSynchronousMethod = true )
166+ public boolean pipIsSupported () {
167+ synchronized (irisApiLock ) {
168+ return checkPipIsReady () && pipController .isSupported ();
169+ }
170+ }
171+
172+ @ ReactMethod (isBlockingSynchronousMethod = true )
173+ public boolean pipIsAutoEnterSupported () {
174+ synchronized (irisApiLock ) {
175+ return checkPipIsReady () && pipController .isAutoEnterSupported ();
176+ }
177+ }
178+
179+ @ ReactMethod (isBlockingSynchronousMethod = true )
180+ public boolean isPipActivated () {
181+ synchronized (irisApiLock ) {
182+ return checkPipIsReady () && pipController .isActivated ();
183+ }
184+ }
185+
186+ @ ReactMethod (isBlockingSynchronousMethod = true )
187+ public boolean pipSetup (ReadableMap options ) {
188+ synchronized (irisApiLock ) {
189+ if (!checkPipIsReady ()) {
190+ return false ;
191+ }
192+ Rational aspectRatio = null ;
193+ if (options .hasKey ("aspectRatioX" ) && options .hasKey ("aspectRatioY" )) {
194+ aspectRatio = new Rational (options .getInt ("aspectRatioX" ),
195+ options .getInt ("aspectRatioY" ));
196+ }
197+ Boolean autoEnterEnabled = null ;
198+ if (options .hasKey ("autoEnterEnabled" )) {
199+ autoEnterEnabled = options .getBoolean ("autoEnterEnabled" );
200+ }
201+ Rect sourceRectHint = null ;
202+ if (options .hasKey ("sourceRectHintLeft" ) &&
203+ options .hasKey ("sourceRectHintTop" ) &&
204+ options .hasKey ("sourceRectHintRight" ) &&
205+ options .hasKey ("sourceRectHintBottom" )) {
206+ sourceRectHint = new Rect (
207+ options .getInt ("sourceRectHintLeft" ),
208+ options .getInt ("sourceRectHintTop" ),
209+ options .getInt ("sourceRectHintRight" ),
210+ options .getInt ("sourceRectHintBottom" ));
211+ }
212+ Boolean seamlessResizeEnabled = null ;
213+ if (options .hasKey ("seamlessResizeEnabled" )) {
214+ seamlessResizeEnabled = options .getBoolean ("seamlessResizeEnabled" );
215+ }
216+ Boolean useExternalStateMonitor = null ;
217+ if (options .hasKey ("useExternalStateMonitor" )) {
218+ useExternalStateMonitor = options .getBoolean ("useExternalStateMonitor" );
219+ } else {
220+ useExternalStateMonitor = true ;
221+ }
222+ Integer externalStateMonitorInterval = null ;
223+ if (options .hasKey ("externalStateMonitorInterval" )) {
224+ externalStateMonitorInterval = options .getInt ("externalStateMonitorInterval" );
225+ } else {
226+ externalStateMonitorInterval = 100 ;
227+ }
228+ boolean result = pipController .setup (
229+ aspectRatio , autoEnterEnabled , sourceRectHint ,
230+ seamlessResizeEnabled , useExternalStateMonitor ,
231+ externalStateMonitorInterval );
232+ return result ;
233+ }
234+ }
235+
236+ @ ReactMethod (isBlockingSynchronousMethod = true )
237+ public boolean pipStart () {
238+ synchronized (irisApiLock ) {
239+ return checkPipIsReady () && pipController .start ();
240+ }
241+ }
242+
243+ @ ReactMethod (isBlockingSynchronousMethod = true )
244+ public void pipStop () {
245+ synchronized (irisApiLock ) {
246+ if (checkPipIsReady ()) {
247+ pipController .stop ();
248+ }
249+ }
250+ }
251+
252+ @ ReactMethod (isBlockingSynchronousMethod = true )
253+ public void pipDispose () {
254+ synchronized (irisApiLock ) {
255+ if (checkPipIsReady ()) {
256+ pipController .dispose ();
257+ }
258+ }
259+ }
260+
113261 @ Override
114262 public void OnEvent (String event , String data , List <byte []> buffers ) {
115263 final WritableMap map = Arguments .createMap ();
0 commit comments