From 5b0e5ab68dba9b1a1a9cac16c642123047dbd533 Mon Sep 17 00:00:00 2001 From: Deepu Ganapathiyadan Date: Fri, 26 Jun 2020 17:48:06 +0530 Subject: [PATCH] Add support for activity scoped navigation request handlers This gives more flexibility for applications that follows a complex UI design --- .../core/ElectrodeBaseActivityDelegate.java | 17 ++- .../api/impl/core/UpdatePropsListener.java | 3 +- .../navigation/ElectrodeBaseActivity.java | 43 +++++-- .../ElectrodeNavigationActivityDelegate.java | 94 +++++++++++++++ .../ElectrodeNavigationFragmentDelegate.java | 108 +++++++++--------- .../navigation/MiniAppNavigationFragment.java | 11 +- .../navigation/NavigationLaunchConfig.java | 35 ++++++ .../navigation/NavigationRouteHandler.java | 7 ++ .../moviesreloaded/MainApplication.java | 4 + .../demo/defaultbehavior/DefaultActivity.java | 18 ++- 10 files changed, 270 insertions(+), 70 deletions(-) create mode 100644 android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationActivityDelegate.java create mode 100644 android/lib/src/main/java/com/ern/api/impl/navigation/NavigationLaunchConfig.java create mode 100644 android/lib/src/main/java/com/ern/api/impl/navigation/NavigationRouteHandler.java diff --git a/android/lib/src/main/java/com/ern/api/impl/core/ElectrodeBaseActivityDelegate.java b/android/lib/src/main/java/com/ern/api/impl/core/ElectrodeBaseActivityDelegate.java index d3da77c0..c74baf75 100644 --- a/android/lib/src/main/java/com/ern/api/impl/core/ElectrodeBaseActivityDelegate.java +++ b/android/lib/src/main/java/com/ern/api/impl/core/ElectrodeBaseActivityDelegate.java @@ -21,13 +21,14 @@ import static com.ern.api.impl.core.ActivityDelegateConstants.KEY_REGISTER_NAV_VIEW_MODEL; import static com.ern.api.impl.core.ElectrodeReactFragmentDelegate.MiniAppRequestListener.ADD_TO_BACKSTACK; +import static com.ern.api.impl.core.LaunchConfig.NONE; -public class ElectrodeBaseActivityDelegate extends ElectrodeReactActivityDelegate implements LifecycleObserver { +public class ElectrodeBaseActivityDelegate extends ElectrodeReactActivityDelegate implements LifecycleObserver { private static final String TAG = ElectrodeBaseActivityDelegate.class.getSimpleName(); @SuppressWarnings("WeakerAccess") protected FragmentActivity mFragmentActivity; - private final LaunchConfig mDefaultLaunchConfig; + protected final T mDefaultLaunchConfig; private final String mRootComponentName; /** @@ -36,7 +37,7 @@ public class ElectrodeBaseActivityDelegate extends ElectrodeReactActivityDelegat * @param defaultLaunchConfig : {@link LaunchConfig} that acts as the the initial configuration to load the rootComponent as well as the default launch config for subsequent navigation flows. * This configuration will also be used as a default configuration when the root component tries to navigate to a new pages if a proper launch config is passed inside {@link #startMiniAppFragment(String, LaunchConfig)}. */ - public ElectrodeBaseActivityDelegate(@NonNull FragmentActivity activity, @Nullable String rootComponentName, @NonNull LaunchConfig defaultLaunchConfig) { + public ElectrodeBaseActivityDelegate(@NonNull FragmentActivity activity, @Nullable String rootComponentName, @NonNull T defaultLaunchConfig) { super(activity, null); mFragmentActivity = activity; @@ -145,13 +146,17 @@ public void startMiniAppFragment(@NonNull String componentName, @NonNull LaunchC switchToFragment(fragment, launchConfig, componentName); } + protected boolean fragmentScopedNavModel() { + return true; + } + private void switchToFragment(@NonNull Fragment fragment, @NonNull LaunchConfig launchConfig, @Nullable String tag) { if (fragment instanceof DialogFragment) { Logger.d(TAG, "Showing dialog fragment"); ((DialogFragment) fragment).show(getFragmentManager(launchConfig), tag); } else { final FragmentManager fragmentManager = getFragmentManager(launchConfig); - int fragmentContainerId = (launchConfig.mFragmentContainerId != LaunchConfig.NONE) ? launchConfig.mFragmentContainerId : mDefaultLaunchConfig.mFragmentContainerId; + int fragmentContainerId = (launchConfig.mFragmentContainerId != NONE) ? launchConfig.mFragmentContainerId : mDefaultLaunchConfig.mFragmentContainerId; final FragmentTransaction transaction = fragmentManager.beginTransaction(); manageTransition(transaction); @@ -161,14 +166,14 @@ private void switchToFragment(@NonNull Fragment fragment, @NonNull LaunchConfig transaction.addToBackStack(tag); } - if (fragmentContainerId != LaunchConfig.NONE) { + if (fragmentContainerId != NONE) { if (launchConfig.mShowAsOverlay) { Logger.d(TAG, "performing ADD fragment inside fragment container"); transaction.add(fragmentContainerId, fragment, tag); } else { Logger.d(TAG, "performing REPLACE fragment inside fragment container"); if (fragment.getArguments() != null) { - fragment.getArguments().putBoolean(KEY_REGISTER_NAV_VIEW_MODEL, true); + fragment.getArguments().putBoolean(KEY_REGISTER_NAV_VIEW_MODEL, fragmentScopedNavModel()); } transaction.replace(fragmentContainerId, fragment, tag); } diff --git a/android/lib/src/main/java/com/ern/api/impl/core/UpdatePropsListener.java b/android/lib/src/main/java/com/ern/api/impl/core/UpdatePropsListener.java index 7382e2c0..de3cbf5f 100644 --- a/android/lib/src/main/java/com/ern/api/impl/core/UpdatePropsListener.java +++ b/android/lib/src/main/java/com/ern/api/impl/core/UpdatePropsListener.java @@ -5,7 +5,8 @@ import androidx.annotation.Nullable; /** - * Used for updating the props for a React Native view component + * Used for updating the props for a React Native view component. + * This is mainly used while going back to a previous fragment that requires new props being passed to the previous fragment. * Refer {@link com.ern.api.impl.navigation.MiniAppNavigationFragment} for usage */ public interface UpdatePropsListener { diff --git a/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeBaseActivity.java b/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeBaseActivity.java index 36ca9646..d216e243 100644 --- a/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeBaseActivity.java +++ b/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeBaseActivity.java @@ -15,9 +15,9 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; -import com.ern.api.impl.core.ElectrodeBaseActivityDelegate; import com.ern.api.impl.core.LaunchConfig; import com.facebook.react.ReactRootView; +import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; import org.json.JSONObject; @@ -25,7 +25,9 @@ public abstract class ElectrodeBaseActivity extends AppCompatActivity implements public static final int DEFAULT_TITLE = -1; public static final int NONE = 0; - protected ElectrodeBaseActivityDelegate mElectrodeReactNavDelegate; + private static final String TAG = ElectrodeBaseActivity.class.getSimpleName(); + + protected ElectrodeNavigationActivityDelegate mElectrodeReactNavDelegate; /** * Override and provide the main layout resource. @@ -42,7 +44,7 @@ public abstract class ElectrodeBaseActivity extends AppCompatActivity implements */ @NonNull protected abstract String getRootComponentName(); - + /** * Id for the fragment container. * @@ -70,7 +72,7 @@ protected Bundle getProps() { protected int title() { return DEFAULT_TITLE; } - + /** * Initial/Default fragment used by the activity to host a react native view. * @@ -96,12 +98,39 @@ protected boolean hideNavBar() { * @return ElectrodeReactFragmentActivityDelegate */ @NonNull - protected ElectrodeBaseActivityDelegate createElectrodeDelegate() { - return new ElectrodeBaseActivityDelegate(this, getRootComponentName(), createDefaultLaunchConfig()); + protected ElectrodeNavigationActivityDelegate createElectrodeDelegate() { + return new ElectrodeNavigationActivityDelegate(this, getRootComponentName(), createNavigationLaunchConfig()); + } + + /** + * Default configuration provided for navigation. + * + * @return NavigationLaunchConfig + */ + protected NavigationLaunchConfig createNavigationLaunchConfig() { + LaunchConfig navConfig = createDefaultLaunchConfig(); + if (navConfig instanceof NavigationLaunchConfig) { + return (NavigationLaunchConfig) navConfig; + } else { + if (navConfig != null) { + Logger.w(TAG, "createDefaultLaunchConfig() is Deprecated, your default launch config is IGNORED, please move to createNavigationLaunchConfig"); + } + return createNavLaunchConfigInternal(); + } } + /** + * Keeping this method for backward compatibility + * + * @deprecated use {@link #createNavigationLaunchConfig()} + */ + @Deprecated protected LaunchConfig createDefaultLaunchConfig() { - LaunchConfig defaultLaunchConfig = new LaunchConfig(); + return createNavLaunchConfigInternal(); + } + + private NavigationLaunchConfig createNavLaunchConfigInternal() { + NavigationLaunchConfig defaultLaunchConfig = new NavigationLaunchConfig(); defaultLaunchConfig.setFragmentClass(miniAppFragmentClass()); defaultLaunchConfig.setFragmentContainerId(getFragmentContainerId()); defaultLaunchConfig.setFragmentManager(getSupportFragmentManager()); diff --git a/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationActivityDelegate.java b/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationActivityDelegate.java new file mode 100644 index 00000000..5ef64a2d --- /dev/null +++ b/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationActivityDelegate.java @@ -0,0 +1,94 @@ +package com.ern.api.impl.navigation; + +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.Observer; +import androidx.lifecycle.OnLifecycleEvent; +import androidx.lifecycle.ViewModelProvider; + +import com.ern.api.impl.core.ElectrodeBaseActivityDelegate; +import com.ern.api.impl.core.LaunchConfig; +import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; + +public class ElectrodeNavigationActivityDelegate extends ElectrodeBaseActivityDelegate { + + private static final String TAG = ElectrodeNavigationActivityDelegate.class.getSimpleName(); + + @Nullable + private ReactNavigationViewModel mNavViewModel; + + /** + * @param activity Hosting activity + * @param rootComponentName First react native component to be launched. + * @param defaultLaunchConfig : {@link LaunchConfig} that acts as the the initial configuration to load the rootComponent as well as the default launch config for subsequent navigation flows. + * This configuration will also be used as a default configuration when the root component tries to navigate to a new pages if a proper launch config is passed inside {@link #startMiniAppFragment(String, LaunchConfig)}. + */ + public ElectrodeNavigationActivityDelegate(@NonNull FragmentActivity activity, @Nullable String rootComponentName, @NonNull NavigationLaunchConfig defaultLaunchConfig) { + super(activity, rootComponentName, defaultLaunchConfig); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + if (mDefaultLaunchConfig.mUseActivityScopedNavigation) { + registerNavRequestHandler(); + } + super.onCreate(savedInstanceState); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) + @Override + public void onResume() { + super.onResume(); + if (mDefaultLaunchConfig.mUseActivityScopedNavigation && mNavViewModel != null) { + mNavViewModel.registerNavRequestHandler(); + } + } + + @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) + @Override + public void onPause() { + super.onPause(); + if (mDefaultLaunchConfig.mUseActivityScopedNavigation && mNavViewModel != null) { + mNavViewModel.unRegisterNavRequestHandler(); + } + } + + private void registerNavRequestHandler() { + mNavViewModel = new ViewModelProvider(mFragmentActivity, new ViewModelProvider.NewInstanceFactory()).get(ReactNavigationViewModel.class); + mNavViewModel.getRouteLiveData().observe(mFragmentActivity, new Observer() { + @Override + public void onChanged(Route route) { + Logger.d(TAG, "Navigation request handled by Activity(%s)", mFragmentActivity); + NavigationRouteHandler routeHandler = null; + if (mDefaultLaunchConfig.mRouteHandlerProvider != null && mDefaultLaunchConfig.mRouteHandlerProvider.getRouteHandler() != null) { + Logger.v(TAG, "Getting route handler via RouteHandlerProvider"); + routeHandler = mDefaultLaunchConfig.mRouteHandlerProvider.getRouteHandler(); + } else { + Fragment f = mFragmentActivity.getSupportFragmentManager().findFragmentById(mDefaultLaunchConfig.getFragmentContainerId()); + if (f instanceof NavigationRouteHandler) { + Logger.v(TAG, "Getting fragment(route handler) hosted inside getFragmentContainer of activity"); + routeHandler = (NavigationRouteHandler) f; + } else { + Logger.w(TAG, "Fragment: %s is not a NavigationRouteHandler", f); + } + } + + if (routeHandler != null) { + routeHandler.handleRoute(route); + } else { + throw new IllegalStateException("Should never reach here. Missing route handler"); + } + } + }); + mNavViewModel.registerNavRequestHandler(); + } + + protected boolean fragmentScopedNavModel() { + return !mDefaultLaunchConfig.mUseActivityScopedNavigation; + } +} diff --git a/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationFragmentDelegate.java b/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationFragmentDelegate.java index 4a8e7f40..7ef53584 100644 --- a/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationFragmentDelegate.java +++ b/android/lib/src/main/java/com/ern/api/impl/navigation/ElectrodeNavigationFragmentDelegate.java @@ -57,64 +57,68 @@ public class ElectrodeNavigationFragmentDelegate routeObserver = new Observer() { @Override public void onChanged(@Nullable Route route) { - if (route != null && !route.isCompleted()) { - Logger.d(TAG, "Delegate: %s received a new navigation route: %s", ElectrodeNavigationFragmentDelegate.this, route.getArguments()); + handleRoute(route, null); + } + }; - if (!route.getArguments().containsKey(KEY_NAV_TYPE)) { - throw new IllegalStateException("Missing NAV_TYPE in route arguments"); - } - Fragment topOfTheStackFragment = getTopOfTheStackFragment(); - - //NOTE: We can't put KEY_NAV_TYPE as a parcelable since ReactNative side does not support Parcelable deserialization yet. - ReactNavigationViewModel.Type navType = ReactNavigationViewModel.Type.valueOf(route.getArguments().getString(KEY_NAV_TYPE)); - if (topOfTheStackFragment == mFragment) { - switch (navType) { - case NAVIGATE: - navigate(route); - break; - case UPDATE: - update(route); - break; - case BACK: - back(route); - break; - case FINISH: - finish(route); - break; - } - } else if (topOfTheStackFragment instanceof ComponentAsOverlay) { - // When the top of the stack fragment is an overlay, the non-overlay fragment below it acts as the parent who is handling it's overlay children and it's navigation flows. - // This is because, overlay fragments are added to the stack by calling FragmentTransactionManager's add() method and not replace(). - // When added, the new fragment's onResume() state is reached by keeping the parent fragment also in a resumed state. Hence the parent need to delegate the navigation calls to the child overlays. - Logger.i(TAG, "Delegating %s request to an overlay component.", navType); - ComponentAsOverlay overlayFragment = (ComponentAsOverlay) topOfTheStackFragment; - switch (navType) { - case NAVIGATE: - overlayFragment.navigate(route); - break; - case UPDATE: - overlayFragment.update(route); - break; - case BACK: - overlayFragment.back(route); - break; - case FINISH: - overlayFragment.finish(route); - break; - } - } else { - throw new RuntimeException("Should never reach here. The fragment handling a navigation api request should be either the current fragment or the top of the stack fragment should implement ComponentAsOverlay. topOfTheStackFragment:" + topOfTheStackFragment); - } + protected void handleRoute(@Nullable Route route, @Nullable Fragment currentVisibleFragment) { + if (route != null && !route.isCompleted()) { + Logger.d(TAG, "Delegate: %s received a new navigation route: %s", ElectrodeNavigationFragmentDelegate.this, route.getArguments()); - if (!route.isCompleted()) { - throw new RuntimeException("Should never reach here. A result should be set for the route at this point. Make sure a setResult is called on the route object after the appropriate action is taken on a navigation request"); + if (!route.getArguments().containsKey(KEY_NAV_TYPE)) { + throw new IllegalStateException("Missing NAV_TYPE in route arguments"); + } + Fragment topOfTheStackFragment = currentVisibleFragment != null ? currentVisibleFragment : getTopOfTheStackFragment(); + + //NOTE: We can't put KEY_NAV_TYPE as a parcelable since ReactNative side does not support Parcelable deserialization yet. + ReactNavigationViewModel.Type navType = ReactNavigationViewModel.Type.valueOf(route.getArguments().getString(KEY_NAV_TYPE)); + if (topOfTheStackFragment == mFragment) { + switch (navType) { + case NAVIGATE: + navigate(route); + break; + case UPDATE: + update(route); + break; + case BACK: + back(route); + break; + case FINISH: + finish(route); + break; + } + } else if (topOfTheStackFragment instanceof ComponentAsOverlay) { + // When the top of the stack fragment is an overlay, the non-overlay fragment below it acts as the parent who is handling it's overlay children and it's navigation flows. + // This is because, overlay fragments are added to the stack by calling FragmentTransactionManager's add() method and not replace(). + // When added, the new fragment's onResume() state is reached by keeping the parent fragment also in a resumed state. Hence the parent need to delegate the navigation calls to the child overlays. + Logger.i(TAG, "Delegating %s request to an overlay component.", navType); + ComponentAsOverlay overlayFragment = (ComponentAsOverlay) topOfTheStackFragment; + switch (navType) { + case NAVIGATE: + overlayFragment.navigate(route); + break; + case UPDATE: + overlayFragment.update(route); + break; + case BACK: + overlayFragment.back(route); + break; + case FINISH: + overlayFragment.finish(route); + break; } - Logger.d(TAG, "Nav request handling completed by: %s", topOfTheStackFragment); } else { - Logger.d(TAG, "Delegate: %s has ignored an already handled route: %s, ", ElectrodeNavigationFragmentDelegate.this, route != null ? route.getArguments() : null); + throw new RuntimeException("Should never reach here. The fragment handling a navigation api request should be either the current fragment or the top of the stack fragment should implement ComponentAsOverlay. topOfTheStackFragment:" + topOfTheStackFragment); + } + + if (!route.isCompleted()) { + throw new RuntimeException("Should never reach here. A result should be set for the route at this point. Make sure a setResult is called on the route object after the appropriate action is taken on a navigation request"); } + Logger.d(TAG, "Nav request handling completed by: %s", topOfTheStackFragment); + } else { + Logger.d(TAG, "Delegate: %s has ignored an already handled route: %s, ", ElectrodeNavigationFragmentDelegate.this, route != null ? route.getArguments() : null); } - }; + } /** * @param fragment {@link Fragment} current Fragment diff --git a/android/lib/src/main/java/com/ern/api/impl/navigation/MiniAppNavigationFragment.java b/android/lib/src/main/java/com/ern/api/impl/navigation/MiniAppNavigationFragment.java index 9d6e62a8..46672efc 100644 --- a/android/lib/src/main/java/com/ern/api/impl/navigation/MiniAppNavigationFragment.java +++ b/android/lib/src/main/java/com/ern/api/impl/navigation/MiniAppNavigationFragment.java @@ -11,13 +11,16 @@ import com.ern.api.impl.core.ElectrodeBaseFragment; import com.ern.api.impl.core.LaunchConfig; import com.ern.api.impl.core.UpdatePropsListener; +import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; /** * Default fragment for Electrode Native Navigation *

* Use this fragment to host a React Native component that uses ern-navigation library to navigate between pages. */ -public class MiniAppNavigationFragment extends ElectrodeBaseFragment implements ElectrodeNavigationFragmentDelegate.FragmentNavigator, ElectrodeNavigationFragmentDelegate.OnUpdateNextPageLaunchConfigListener, UpdatePropsListener { +public class MiniAppNavigationFragment extends ElectrodeBaseFragment implements ElectrodeNavigationFragmentDelegate.FragmentNavigator, ElectrodeNavigationFragmentDelegate.OnUpdateNextPageLaunchConfigListener, UpdatePropsListener, NavigationRouteHandler { + private static final String TAG = MiniAppNavigationFragment.class.getSimpleName(); + @NonNull @Override protected ElectrodeNavigationFragmentDelegate createFragmentDelegate() { @@ -50,4 +53,10 @@ public void updateNextPageLaunchConfig(@NonNull String nextPageName, @NonNull La public void refresh(@Nullable Bundle data) { mElectrodeReactFragmentDelegate.refresh(data); } + + @Override + public void handleRoute(@NonNull Route route) { + Logger.v(TAG, "Delegating handleRoute request for route: %s", route); + mElectrodeReactFragmentDelegate.handleRoute(route, this); + } } diff --git a/android/lib/src/main/java/com/ern/api/impl/navigation/NavigationLaunchConfig.java b/android/lib/src/main/java/com/ern/api/impl/navigation/NavigationLaunchConfig.java new file mode 100644 index 00000000..f7fe6914 --- /dev/null +++ b/android/lib/src/main/java/com/ern/api/impl/navigation/NavigationLaunchConfig.java @@ -0,0 +1,35 @@ +package com.ern.api.impl.navigation; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.ern.api.impl.core.ElectrodeBaseActivityDelegate; +import com.ern.api.impl.core.LaunchConfig; + +public class NavigationLaunchConfig extends LaunchConfig { + boolean mUseActivityScopedNavigation; + + RouteHandlerProvider mRouteHandlerProvider; + + /** + * Use this when you don't need each fragment to register it's own navigation request handlers. + * When true: {@link com.ern.api.impl.navigation.ReactNavigationViewModel} will be created with activity scope instead of fragment scope. + * The activity will then delegate the navigation requests to the corresponding fragments via {@link com.ern.api.impl.navigation.NavigationRouteHandler} implementation. + * The {@link ElectrodeBaseActivityDelegate} will take the current instance of the {@link Fragment} that is loaded inside {@link LaunchConfig#getFragmentContainerId()}. Assumption is that this fragment implements {@link NavigationRouteHandler} + * Pass {@link RouteHandlerProvider} If you would like to provide your own implementation of providing the fragment instance, valid only if #value is true. + */ + public void useActivityScopeForNavigation(boolean value, @Nullable RouteHandlerProvider routeHandlerProvider) { + mUseActivityScopedNavigation = value; + mRouteHandlerProvider = routeHandlerProvider; + } + + public interface RouteHandlerProvider { + /** + * Provide the current visible fragment that is hosting the React Native view component which needs to handle the navigation request + * + * @return Fragment implements {@link NavigationRouteHandler} + */ + @Nullable + T getRouteHandler(); + } +} diff --git a/android/lib/src/main/java/com/ern/api/impl/navigation/NavigationRouteHandler.java b/android/lib/src/main/java/com/ern/api/impl/navigation/NavigationRouteHandler.java new file mode 100644 index 00000000..bc15df37 --- /dev/null +++ b/android/lib/src/main/java/com/ern/api/impl/navigation/NavigationRouteHandler.java @@ -0,0 +1,7 @@ +package com.ern.api.impl.navigation; + +import androidx.annotation.NonNull; + +public interface NavigationRouteHandler { + void handleRoute(@NonNull Route route); +} diff --git a/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/MainApplication.java b/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/MainApplication.java index c7f1630c..418e4c95 100644 --- a/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/MainApplication.java +++ b/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/MainApplication.java @@ -2,6 +2,7 @@ import android.app.Application; +import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; import com.walmartlabs.ern.container.ElectrodeReactContainer; public class MainApplication extends Application { @@ -13,5 +14,8 @@ public void onCreate() { this, new ElectrodeReactContainer.Config().isReactNativeDeveloperSupport(true) /* Add your additional plugins configuration here */); + if (BuildConfig.DEBUG) { + Logger.overrideLogLevel(Logger.LogLevel.VERBOSE); + } } } diff --git a/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/demo/defaultbehavior/DefaultActivity.java b/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/demo/defaultbehavior/DefaultActivity.java index d8711ded..f91b7d17 100644 --- a/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/demo/defaultbehavior/DefaultActivity.java +++ b/android/moviesreloaded/src/main/java/com/walmartlabs/moviesreloaded/demo/defaultbehavior/DefaultActivity.java @@ -3,12 +3,14 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; -import com.ern.api.impl.core.LaunchConfig; import com.ern.api.impl.navigation.ElectrodeBaseActivity; import com.ern.api.impl.navigation.MiniAppNavigationFragment; +import com.ern.api.impl.navigation.NavigationLaunchConfig; +import com.walmartlabs.electrode.reactnative.bridge.helpers.Logger; import com.walmartlabs.moviesreloaded.R; public class DefaultActivity extends ElectrodeBaseActivity { + private static final String TAG = DefaultActivity.class.getSimpleName(); @NonNull @Override @@ -33,9 +35,19 @@ protected Class miniAppFragmentClass() { } @Override - protected LaunchConfig createDefaultLaunchConfig() { - LaunchConfig config = super.createDefaultLaunchConfig(); + protected NavigationLaunchConfig createNavigationLaunchConfig() { + NavigationLaunchConfig config = super.createNavigationLaunchConfig(); config.setForceUpEnabled(true); + config.useActivityScopeForNavigation(true, (NavigationLaunchConfig.RouteHandlerProvider) () -> { + Logger.v(TAG, "Entering getRouteHandler() implementation"); + Fragment f = getSupportFragmentManager().findFragmentById(getFragmentContainerId()); + if (f instanceof MiniAppNavigationFragment) { + Logger.v(TAG, "Getting fragment(route handler) hosted inside getFragmentContainer of activity"); + return (MiniAppNavigationFragment) f; + } else { + return null; + } + }); return config; } }