From 9cbcbf6e26d32f605afee9485841e01be72ee7eb Mon Sep 17 00:00:00 2001 From: paweldomas Date: Tue, 17 Apr 2018 13:06:57 -0500 Subject: [PATCH] fix(PictureInPictureModule): catch the RuntimeException Activity.enterPictureInPictureMode can fail for a couple of reasons mentioned in the JSDoc: "The system may disallow entering picture-in-picture in various cases, including when the activity is not visible, if the screen is locked or if the user has an activity pinned." It seems to be safe to assume that those cases will be caught by a RuntimeException handler (only RuntimeExceptions can be left without explicit catch block). Anyway the root cause for problems is the fact that the current process for going to the picture in picture mode is not synchronised with Activity's lifecycle. On Activity's "userLeaveHint" callback we dispatch async task to the JS code which only then after dispatching some more stuff eventually call native method that enter PiP. In case we spend too much time on the JS side and the Activity goes to PAUSED state the call will fail with IllegalStatException: "activity is not visible", "activity is paused" etc. This means with this fix the app will not crash, but we'll see it sometimes not go to the PiP mode as expected. --- .../meet/sdk/PictureInPictureModule.java | 22 ++++++++++++++----- .../mobile/picture-in-picture/actions.js | 4 ++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/android/sdk/src/main/java/org/jitsi/meet/sdk/PictureInPictureModule.java b/android/sdk/src/main/java/org/jitsi/meet/sdk/PictureInPictureModule.java index ff3d0c533..bf15edcc6 100644 --- a/android/sdk/src/main/java/org/jitsi/meet/sdk/PictureInPictureModule.java +++ b/android/sdk/src/main/java/org/jitsi/meet/sdk/PictureInPictureModule.java @@ -44,14 +44,26 @@ public class PictureInPictureModule extends ReactContextBaseJavaModule { PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder() .setAspectRatio(new Rational(1, 1)); - boolean r - = currentActivity.enterPictureInPictureMode(builder.build()); + Throwable error; - if (r) { + // https://developer.android.com/reference/android/app/Activity.html#enterPictureInPictureMode(android.app.PictureInPictureParams) + // + // The system may disallow entering picture-in-picture in various + // cases, including when the activity is not visible, if the screen + // is locked or if the user has an activity pinned. + try { + error + = currentActivity.enterPictureInPictureMode(builder.build()) + ? null + : new Exception("Failed to enter Picture-in-Picture"); + } catch (RuntimeException re) { + error = re; + } + + if (error == null) { promise.resolve(null); } else { - promise.reject( - new Exception("Failed to enter Picture-in-Picture")); + promise.reject(error); } return; diff --git a/react/features/mobile/picture-in-picture/actions.js b/react/features/mobile/picture-in-picture/actions.js index 3102581f9..0a271a2cf 100644 --- a/react/features/mobile/picture-in-picture/actions.js +++ b/react/features/mobile/picture-in-picture/actions.js @@ -23,6 +23,10 @@ export function enterPictureInPicture() { return (dispatch: Dispatch, getState: Function) => { const state = getState(); const { app } = state['features/app']; + + // FIXME We want to be able to enter Picture-in-Picture as soon as we + // are on the Conference page i.e. even before `joining` was set in the + // reducer. const { conference, joining } = state['features/base/conference']; if (app