Get a result from a react native app integrated into an existing android app

Marc :

I found a lot of articles speaking about how to integrate react native into existing android apps. But none of them explains how to get a result back from the react native code in order to use it directly in Java android source code.

Explanations : I have a react native app that is doing a specific job and displays the result in a popup window. I want to integrate this app (doing the necessary modifications) to be able to get this specific result into my android Java source code instead of displaying it into a react native popup.

I searched all the internet but found nothing about this.

Pascal :

In order to get a result back from the activity you started, your module needs to have access to the reference of your activity.
Here are two solutions :
- Declare the module as an inner class of the activity
- Pass a reference of your activity in the constructor of the module

But, remember that your module needs to be used in a ReactPackage, and ReactPackage is an interface, so if you want you can have your ReactActivity implementing the interface (instead of creating a new class).

Here is a full working example using an inner class and an activity implementing ReactPackage :

public class MyReactActivity extends AppCompatActivity 
    implements DefaultHardwareBackBtnHandler, ReactPackage
{
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                // This activity is also a "ReactPackage"
                .addPackage(this)
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        mReactRootView.startReactApplication(mReactInstanceManager, "MyReactComponent", null);

        setContentView(mReactRootView);
    }

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        // The module is added to the ReactPackage
        modules.add(new TestModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    // Module definition as an inner class
    public class TestModule extends ReactContextBaseJavaModule {
        public TestModule(ReactApplicationContext reactContext) {
            super(reactContext);
        }

        @Override
        public String getName() {
            return "TestModule";
        }

        // The function you'll call from React Native
        @ReactMethod
        public void closewithresult(float datafromreact) {
            // Set a result
            Bundle bundle = new Bundle();
            bundle.putFloat("result", datafromreact);
            setResult(Activity.RESULT_OK, (new Intent()).putExtras(bundle));

            // Close the activity
            finish();
        }
    }

    /*
     * Other overrided functions 
     * (not relevant for this question)
     */ 
    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostDestroy(this);
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

}

Then, you can start your ReactActivity like this :

Intent intent = new Intent(getApplicationContext(), MyReactActivity.class);
startActivityForResult(intent, 123);

Get the result like this :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 123 && resultCode == Activity.RESULT_OK) {
        float result = data.getExtras().getFloat("result");
        // Do whatever you want with "result"
    }
}

And just use it in React :

import { NativeModules } from 'react-native';
// [...]
// Call the function
NativeModules.TestModule.closewithresult(654.532);

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=470421&siteId=1