从集成到现有Android应用程序中的react本机应用程序获取结果

时间:2017-10-20 11:31:12

标签: javascript java android react-native

我发现很多文章都在谈论如何将native native整合到现有的Android应用程序中。但它们都没有解释如何从反应本机代码中获取结果,以便直接在Java android源代码中使用它。

解释:我有一个做出特定工作的本机应用程序,并在弹出窗口中显示结果。 我想整合这个应用程序(进行必要的修改),以便能够将这个特定的结果导入我的Android Java源代码,而不是将其显示到反应原生弹出窗口中。

我搜索了所有互联网,但没有发现任何相关信息。

2 个答案:

答案 0 :(得分:3)

也许我不理解你想要做什么......但是你不能只是构建一个原生模块,让你的React Native应用程序调用它的功能。完成将数据传递给您的本机代码?

让我们假设您的应用的React Native部分将用户的名字和姓氏作为输入,然后点击提交。

您可以正常编写RN javascript:将2个TextInput字段及其值映射到您的状态,并使用带有onPress处理程序的Button。在onPress处理程序中,您可以调用Native Module并传递参数

import { 
    NativeModules
} from 'react-native';

const NativeNameSubmission = NativeModules.NameSubmission;

...

    <Button
        onPress={() => NativeNameSubmission.submitName(this.state.firstName, this.state.lastName)}
        title="Submit"/>

您的原生模块看起来像这样:

public class RCTNameSubmission extends ReactContextBaseJavaModule {

    public RCTNameSubmission(ReactApplicationContext reactContext) {
        super(reactContext);
    }

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

    @ReactMethod
    public void submitName(String firstName, String lastName) {
        // save the name data for later use
        ...
        // Exit React App
        getCurrentActivity().finish();
    }
}

答案 1 :(得分:3)

为了从您开始的活动中获得结果,您的模块需要能够访问您的活动参考。
这有两个解决方案:
- 将模块声明为活动的内部类
- 在模块的构造函数中传递活动的引用

但是,请记住,您的模块需要在ReactPackage中使用,ReactPackage是一个接口,因此如果您需要,可以让您的ReactActivity实现接口(而不是创建新类) )。

以下是使用inner class和实施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);
    }

}

然后,您可以像这样开始ReactActivity

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

获得如下结果:

@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"
    }
}

只需在React中使用它:

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