Back out "[react-native][PR] Android - Add a ReactFragment"

Summary: Original commit changeset: b50b708cde45

Reviewed By: mdvacca

Differential Revision: D14792438

fbshipit-source-id: c5e0b5f7663fe70110f73ae94a6fa99388f87ae3
This commit is contained in:
Emily Janzer
2019-04-04 18:35:43 -07:00
committed by Facebook Github Bot
parent 0f909e3318
commit 7944d47a63
3 changed files with 55 additions and 373 deletions

View File

@@ -15,9 +15,10 @@ import android.view.KeyEvent;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Callback;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.PermissionListener;
import com.facebook.react.uimanager.RootView;
import javax.annotation.Nullable;
/**
@@ -30,10 +31,10 @@ public class ReactActivityDelegate {
private final @Nullable Activity mActivity;
private final @Nullable String mMainComponentName;
private @Nullable ReactRootView mReactRootView;
private @Nullable DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
private @Nullable PermissionListener mPermissionListener;
private @Nullable Callback mPermissionsCallback;
private ReactDelegate mReactDelegate;
@Deprecated
public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
@@ -51,7 +52,7 @@ public class ReactActivityDelegate {
}
protected ReactRootView createRootView() {
return mReactDelegate.createRootView();
return new ReactRootView(getContext());
}
/**
@@ -66,7 +67,7 @@ public class ReactActivityDelegate {
}
public ReactInstanceManager getReactInstanceManager() {
return mReactDelegate.getReactInstanceManager();
return getReactNativeHost().getReactInstanceManager();
}
public String getMainComponentName() {
@@ -75,24 +76,36 @@ public class ReactActivityDelegate {
protected void onCreate(Bundle savedInstanceState) {
String mainComponentName = getMainComponentName();
mReactDelegate = new ReactDelegate(getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions());
if (mMainComponentName != null) {
mReactDelegate.loadApp();
getPlainActivity().setContentView(mReactDelegate.getReactRootView());
if (mainComponentName != null) {
loadApp(mainComponentName);
}
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
}
protected void loadApp(String appKey) {
mReactDelegate.loadApp(appKey);
getPlainActivity().setContentView(mReactDelegate.getReactRootView());
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),
appKey,
getLaunchOptions());
getPlainActivity().setContentView(mReactRootView);
}
protected void onPause() {
mReactDelegate.onHostPause();
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostPause(getPlainActivity());
}
}
protected void onResume() {
mReactDelegate.onHostResume();
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostResume(
getPlainActivity(),
(DefaultHardwareBackBtnHandler) getPlainActivity());
}
if (mPermissionsCallback != null) {
mPermissionsCallback.invoke();
@@ -101,11 +114,20 @@ public class ReactActivityDelegate {
}
protected void onDestroy() {
mReactDelegate.onHostDestroy();
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
mReactRootView = null;
}
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostDestroy(getPlainActivity());
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mReactDelegate.onActivityResult(requestCode, resultCode, data, true);
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager()
.onActivityResult(getPlainActivity(), requestCode, resultCode, data);
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
@@ -119,7 +141,19 @@ public class ReactActivityDelegate {
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
return true;
}
boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer)
.didDoubleTapR(keyCode, getPlainActivity().getCurrentFocus());
if (didDoubleTapR) {
getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
return true;
}
}
return false;
}
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
@@ -133,7 +167,11 @@ public class ReactActivityDelegate {
}
public boolean onBackPressed() {
return mReactDelegate.onBackPressed();
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onBackPressed();
return true;
}
return false;
}
public boolean onNewIntent(Intent intent) {

View File

@@ -1,147 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import javax.annotation.Nullable;
/**
* A delegate for handling React Application support. This delegate is unaware whether it is used in
* an {@link Activity} or a {@link android.app.Fragment}.
*/
public class ReactDelegate {
private final Activity mActivity;
private ReactRootView mReactRootView;
@Nullable
private final String mMainComponentName;
@Nullable
private Bundle mLaunchOptions;
@Nullable
private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
private ReactNativeHost mReactNativeHost;
public ReactDelegate(Activity activity, ReactNativeHost reactNativeHost, @Nullable String appKey, @Nullable Bundle launchOptions) {
mActivity = activity;
mMainComponentName = appKey;
mLaunchOptions = launchOptions;
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
mReactNativeHost = reactNativeHost;
}
public void onHostResume() {
if (getReactNativeHost().hasInstance()) {
if (mActivity instanceof DefaultHardwareBackBtnHandler) {
getReactNativeHost().getReactInstanceManager().onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
} else {
throw new ClassCastException("Host Activity does not implement DefaultHardwareBackBtnHandler");
}
}
}
public void onHostPause() {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostPause(mActivity);
}
}
public void onHostDestroy() {
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
mReactRootView = null;
}
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onHostDestroy(mActivity);
}
}
public boolean onBackPressed() {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onBackPressed();
return true;
}
return false;
}
public void onActivityResult(int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) {
if (getReactNativeHost().hasInstance() && shouldForwardToReactInstance) {
getReactNativeHost().getReactInstanceManager().onActivityResult(mActivity, requestCode, resultCode, data);
}
}
public void loadApp() {
loadApp(mMainComponentName);
}
public void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),
appKey,
mLaunchOptions);
}
public ReactRootView getReactRootView() {
return mReactRootView;
}
protected ReactRootView createRootView() {
return new ReactRootView(mActivity);
}
/**
* Handles delegating the {@link Activity#onKeyUp(int, KeyEvent)} method to determine whether
* the application should show the developer menu or should reload the React Application.
*
* @return true if we consume the event and either shoed the develop menu or reloaded the application.
*/
public boolean shouldShowDevMenuOrReload(int keyCode, KeyEvent event) {
if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
return true;
}
boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer).didDoubleTapR(keyCode, mActivity.getCurrentFocus());
if (didDoubleTapR) {
getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
return true;
}
}
return false;
}
/**
* Get the {@link ReactNativeHost} used by this app.
*/
private ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
public ReactInstanceManager getReactInstanceManager() {
return getReactNativeHost().getReactInstanceManager();
}
}

View File

@@ -1,209 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.modules.core.PermissionAwareActivity;
import com.facebook.react.modules.core.PermissionListener;
import javax.annotation.Nullable;
import androidx.fragment.app.Fragment;
/**
* Fragment for creating a React View. This allows the developer to "embed" a React Application
* inside native components such as a Drawer, ViewPager, etc.
*/
public class ReactFragment extends Fragment implements PermissionAwareActivity {
private static final String ARG_COMPONENT_NAME = "arg_component_name";
private static final String ARG_LAUNCH_OPTIONS = "arg_launch_options";
private ReactDelegate mReactDelegate;
@Nullable
private PermissionListener mPermissionListener;
public ReactFragment() {
// Required empty public constructor
}
/**
* @param componentName The name of the react native component
* @return A new instance of fragment ReactFragment.
*/
private static ReactFragment newInstance(String componentName, Bundle launchOptions) {
ReactFragment fragment = new ReactFragment();
Bundle args = new Bundle();
args.putString(ARG_COMPONENT_NAME, componentName);
args.putBundle(ARG_LAUNCH_OPTIONS, launchOptions);
fragment.setArguments(args);
return fragment;
}
// region Lifecycle
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String mainComponentName = null;
Bundle launchOptions = null;
if (getArguments() != null) {
mainComponentName = getArguments().getString(ARG_COMPONENT_NAME);
launchOptions = getArguments().getBundle(ARG_LAUNCH_OPTIONS);
}
if (mainComponentName == null) {
throw new IllegalStateException("Cannot loadApp if component name is null");
}
mReactDelegate = new ReactDelegate(getActivity(), getReactNativeHost(), mainComponentName, launchOptions);
}
/**
* Get the {@link ReactNativeHost} used by this app. By default, assumes
* {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
* does not implement {@code ReactApplication} or you simply have a different mechanism for
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
*/
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getActivity().getApplication()).getReactNativeHost();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mReactDelegate.loadApp();
return mReactDelegate.getReactRootView();
}
@Override
public void onResume() {
super.onResume();
mReactDelegate.onHostResume();
}
@Override
public void onPause() {
super.onPause();
mReactDelegate.onHostPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mReactDelegate.onHostDestroy();
}
// endregion
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mReactDelegate.onActivityResult(requestCode, resultCode, data, false);
}
/**
* Helper to forward hardware back presses to our React Native Host
*
* This must be called via a forward from your host Activity
*
*/
public boolean onBackPressed() {
return mReactDelegate.onBackPressed();
}
/**
* Helper to forward onKeyUp commands from our host Activity.
* This allows ReactFragment to handle double tap reloads and dev menus
*
* This must be called via a forward from your host Activity
*
* @param keyCode keyCode
* @param event event
* @return true if we handled onKeyUp
*/
public boolean onKeyUp(int keyCode, KeyEvent event) {
return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (mPermissionListener != null &&
mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
@Override
public int checkPermission(String permission, int pid, int uid) {
return getActivity().checkPermission(permission, pid, uid);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public int checkSelfPermission(String permission) {
return getActivity().checkSelfPermission(permission);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
requestPermissions(permissions, requestCode);
}
/**
* Builder class to help instantiate a ReactFragment
*/
public static class Builder {
String mComponentName;
Bundle mLaunchOptions;
public Builder() {
mComponentName = null;
mLaunchOptions = null;
}
/**
* Set the Component name for our React Native instance.
*
* @param componentName The name of the component
* @return Builder
*/
public Builder setComponentName(String componentName) {
mComponentName = componentName;
return this;
}
/**
* Set the Launch Options for our React Native instance.
*
* @param launchOptions launchOptions
* @return Builder
*/
public Builder setLaunchOptions(Bundle launchOptions) {
mLaunchOptions = launchOptions;
return this;
}
public ReactFragment build() {
return ReactFragment.newInstance(mComponentName, mLaunchOptions);
}
}
}