[Android] Implement DefaultHardwareBackBtnHandler

* Regardless of whether the SDK client/consumer employs
  JitsiMeetActivity or JitsiMeetView, default to finishing the
  associated Activity upon invoking the back button (which is what
  Activity#onBackPressed() is documented to do).

* Do not break the public API of JitsiMeetView and, thus, Jitsi Meet SDK
  for Android.
This commit is contained in:
Lyubo Marinov 2017-09-21 23:52:36 -05:00
parent 35dab19b30
commit ec58aa9959
3 changed files with 106 additions and 24 deletions

View File

@ -0,0 +1,65 @@
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import android.app.Activity;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
/**
* Defines the default behavior of <tt>JitsiMeetActivity</tt> and
* <tt>JitsiMeetView</tt> upon invoking the back button if no
* <tt>JitsiMeetView</tt> handles the invocation. For example, a
* <tt>JitsiMeetView</tt> may (1) handle the invocation of the back button
* during a conference by leaving the conference and (2) not handle the
* invocation when not in a conference.
*/
public class DefaultHardwareBackBtnHandlerImpl
implements DefaultHardwareBackBtnHandler {
/**
* The <tt>Activity</tt> to which the default handling of the back button
* is being provided by this instance.
*/
private final Activity activity;
/**
* Initializes a new <tt>DefaultHardwareBackBtnHandlerImpl</tt> instance to
* provide the default handling of the back button to a specific
* <tt>Activity</tt>.
*
* @param activity - the <tt>Activity</tt> to which the new instance is to
* provide the default behavior of the back button
*/
public DefaultHardwareBackBtnHandlerImpl(Activity activity) {
this.activity = activity;
}
/**
* {@inheritDoc}
*
* Finishes the associated <tt>Activity</tt>.
*/
@Override
public void invokeDefaultOnBackPressed() {
// Technically, we'd like to invoke Activity#onBackPressed().
// Practically, it's not possible. Fortunately, the documentation of
// Activity#onBackPressed() specifies that "[t]he default implementation
// simply finishes the current activity,"
activity.finish();
}
}

View File

@ -40,8 +40,7 @@ import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
* <tt>JKConferenceView</tt> static methods.
*/
public class JitsiMeetActivity
extends AppCompatActivity
implements DefaultHardwareBackBtnHandler {
extends AppCompatActivity {
/**
* The request code identifying requests for the permission to draw on top
@ -50,6 +49,12 @@ public class JitsiMeetActivity
private static final int OVERLAY_PERMISSION_REQUEST_CODE
= (int) (Math.random() * Short.MAX_VALUE);
/**
* The default behavior of this <tt>JitsiMeetActivity</tt> upon invoking the
* back button if {@link #view} does not handle the invocation.
*/
private DefaultHardwareBackBtnHandler defaultBackButtonImpl;
/**
* Instance of the {@link JitsiMeetView} which this activity will display.
*/
@ -133,23 +138,23 @@ public class JitsiMeetActivity
}
}
/**
* This method is called if the JS part does not handle the physical back
* button press.
*/
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
/**
* {@inheritDoc}
*/
@Override
public void onBackPressed() {
if (!JitsiMeetView.onBackPressed()) {
// Invoke the default handler if it wasn't handled by React.
super.onBackPressed();
// JitsiMeetView didn't handle the invocation of the back button.
// Generally, an Activity extender would very likely want to invoke
// Activity#onBackPressed(). For the sake of consistency with
// JitsiMeetView and within the Jitsi Meet SDK for Android though,
// JitsiMeetActivity does what JitsiMeetView would've done if it
// were able to handle the invocation.
if (defaultBackButtonImpl == null) {
super.onBackPressed();
} else {
defaultBackButtonImpl.invokeDefaultOnBackPressed();
}
}
}
@ -206,6 +211,7 @@ public class JitsiMeetActivity
super.onPause();
JitsiMeetView.onHostPause(this);
defaultBackButtonImpl = null;
}
/**
@ -215,7 +221,8 @@ public class JitsiMeetActivity
protected void onResume() {
super.onResume();
JitsiMeetView.onHostResume(this, this);
defaultBackButtonImpl = new DefaultHardwareBackBtnHandlerImpl(this);
JitsiMeetView.onHostResume(this, defaultBackButtonImpl);
}
/**

View File

@ -27,7 +27,6 @@ import android.support.annotation.Nullable;
import android.widget.FrameLayout;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactInstanceManagerBuilder;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
@ -148,11 +147,11 @@ public class JitsiMeetView extends FrameLayout {
* implementation.
*/
public static boolean onBackPressed() {
if (reactInstanceManager != null) {
if (reactInstanceManager == null) {
return false;
} else {
reactInstanceManager.onBackPressed();
return true;
} else {
return false;
}
}
@ -186,14 +185,25 @@ public class JitsiMeetView extends FrameLayout {
* <tt>Activity.onResume</tt> so we can do the required internal processing.
*
* @param activity - <tt>Activity</tt> being resumed.
* @param backHandler - a <tt>DefaultHardwareBackBtnHandler</tt> which
* will handle the back button press in case there's nothing to handle on
* the JS side.
*/
public static void onHostResume(Activity activity,
DefaultHardwareBackBtnHandler backHandler) {
public static void onHostResume(Activity activity) {
onHostResume(activity, new DefaultHardwareBackBtnHandlerImpl(activity));
}
/**
* Activity lifecycle method which should be called from
* <tt>Activity.onResume</tt> so we can do the required internal processing.
*
* @param activity - <tt>Activity</tt> being resumed.
* @param defaultBackButtonImpl - a <tt>DefaultHardwareBackBtnHandler</tt>
* to handle invoking the back button if no <tt>JitsiMeetView</tt> handles
* it.
*/
public static void onHostResume(
Activity activity,
DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
if (reactInstanceManager != null) {
reactInstanceManager.onHostResume(activity, backHandler);
reactInstanceManager.onHostResume(activity, defaultBackButtonImpl);
}
}