mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
a8449c14ac
Summary:
Currently, the final field mMainComponentName is used. This field is
initialized in the constructor of ReactActivityDelegate, and the
ReactActivityDelegate itself is initialized in the constructor of
ReactActivity. This means that the only way you can pass a main
component name to ReactActivityDelegate, is when your ReactActivity
subclass is constructed. At this point in the lifecycle of an
activity, the getIntent() value that the activity was initialized by
returns null, making it impossible to set the mainComponentName
dynamically based on data passed to the activity via an intent.
The mMainComponentName final field is also only used in onCreate of
the delegate, so it's not actually needed by the ReactActivityDelegate
at construction time. So the above limitation is not fundamental, it's
just a side effect of the API design.
By allowing subclasses of ReactActivityDelegate to implement a
getMainComponentName method, the subclass then has full control of how
to initialize the value. So an implementation of getMainComponentName
could be:
public String getMainComponentName() {
return getIntent().getStringExtra("reactMainComponentName");
}
This commit doesn't remove anything and only adds a new method, so it
should be fully backwards compatible.
Thank you for sending the PR! We appreciate you spending the time to work on these changes.
Help us understand your motivation by explaining why you decided to make this change.
<!--
Required: Write your motivation here.
If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->
Pull Request resolved: https://github.com/facebook/react-native/pull/19814
Differential Revision: D14206644
Pulled By: cpojer
fbshipit-source-id: 8532560f944362fe0cce263a7f9a503df8ae539f
216 lines
6.8 KiB
Java
216 lines
6.8 KiB
Java
// 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.Context;
|
|
import android.content.Intent;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
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 javax.annotation.Nullable;
|
|
|
|
/**
|
|
* Delegate class for {@link ReactActivity} and {@link ReactFragmentActivity}. You can subclass this
|
|
* to provide custom implementations for e.g. {@link #getReactNativeHost()}, if your Application
|
|
* class doesn't implement {@link ReactApplication}.
|
|
*/
|
|
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;
|
|
|
|
@Deprecated
|
|
public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
|
|
mActivity = activity;
|
|
mMainComponentName = mainComponentName;
|
|
}
|
|
|
|
public ReactActivityDelegate(ReactActivity activity, @Nullable String mainComponentName) {
|
|
mActivity = activity;
|
|
mMainComponentName = mainComponentName;
|
|
}
|
|
|
|
protected @Nullable Bundle getLaunchOptions() {
|
|
return null;
|
|
}
|
|
|
|
protected ReactRootView createRootView() {
|
|
return new ReactRootView(getContext());
|
|
}
|
|
|
|
/**
|
|
* 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) getPlainActivity().getApplication()).getReactNativeHost();
|
|
}
|
|
|
|
public ReactInstanceManager getReactInstanceManager() {
|
|
return getReactNativeHost().getReactInstanceManager();
|
|
}
|
|
|
|
public String getMainComponentName() {
|
|
return mMainComponentName;
|
|
}
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
String mainComponentName = getMainComponentName();
|
|
if (mainComponentName != null) {
|
|
loadApp(mainComponentName);
|
|
}
|
|
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
|
|
}
|
|
|
|
protected void loadApp(String appKey) {
|
|
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() {
|
|
if (getReactNativeHost().hasInstance()) {
|
|
getReactNativeHost().getReactInstanceManager().onHostPause(getPlainActivity());
|
|
}
|
|
}
|
|
|
|
protected void onResume() {
|
|
if (getReactNativeHost().hasInstance()) {
|
|
getReactNativeHost().getReactInstanceManager().onHostResume(
|
|
getPlainActivity(),
|
|
(DefaultHardwareBackBtnHandler) getPlainActivity());
|
|
}
|
|
|
|
if (mPermissionsCallback != null) {
|
|
mPermissionsCallback.invoke();
|
|
mPermissionsCallback = null;
|
|
}
|
|
}
|
|
|
|
protected void onDestroy() {
|
|
if (mReactRootView != null) {
|
|
mReactRootView.unmountReactApplication();
|
|
mReactRootView = null;
|
|
}
|
|
if (getReactNativeHost().hasInstance()) {
|
|
getReactNativeHost().getReactInstanceManager().onHostDestroy(getPlainActivity());
|
|
}
|
|
}
|
|
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
if (getReactNativeHost().hasInstance()) {
|
|
getReactNativeHost().getReactInstanceManager()
|
|
.onActivityResult(getPlainActivity(), requestCode, resultCode, data);
|
|
}
|
|
}
|
|
|
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
if (getReactNativeHost().hasInstance()
|
|
&& getReactNativeHost().getUseDeveloperSupport()
|
|
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
|
|
event.startTracking();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean onKeyUp(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, getPlainActivity().getCurrentFocus());
|
|
if (didDoubleTapR) {
|
|
getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
|
if (getReactNativeHost().hasInstance()
|
|
&& getReactNativeHost().getUseDeveloperSupport()
|
|
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
|
|
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean onBackPressed() {
|
|
if (getReactNativeHost().hasInstance()) {
|
|
getReactNativeHost().getReactInstanceManager().onBackPressed();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean onNewIntent(Intent intent) {
|
|
if (getReactNativeHost().hasInstance()) {
|
|
getReactNativeHost().getReactInstanceManager().onNewIntent(intent);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@TargetApi(Build.VERSION_CODES.M)
|
|
public void requestPermissions(
|
|
String[] permissions,
|
|
int requestCode,
|
|
PermissionListener listener) {
|
|
mPermissionListener = listener;
|
|
getPlainActivity().requestPermissions(permissions, requestCode);
|
|
}
|
|
|
|
public void onRequestPermissionsResult(
|
|
final int requestCode,
|
|
final String[] permissions,
|
|
final int[] grantResults) {
|
|
mPermissionsCallback = new Callback() {
|
|
@Override
|
|
public void invoke(Object... args) {
|
|
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
|
mPermissionListener = null;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
protected Context getContext() {
|
|
return Assertions.assertNotNull(mActivity);
|
|
}
|
|
|
|
protected Activity getPlainActivity() {
|
|
return ((Activity) getContext());
|
|
}
|
|
}
|