简体   繁体   中英

Calling Native Java method from React Native in Javascript

I am trying to call an Android native method showJ from Javascript in React Native but I keep getting the error :

2019-12-10 20:22:31.959 24712-24861/com.example.myapplication E/ReactNativeJS: TypeError: Cannot read property 'showJ' of null
2019-12-10 20:22:31.976 24712-24712/com.example.myapplication E/unknown:ReactNative: Unable to launch redbox because react activity is not available, here is the error that redbox would've displayed: TypeError: Cannot read property 'showJ' of null, js engine: hermes  

Any help resolving this will be greatly appreciated. Thank you all in advance.

This is how I go about it :

public class MainActivity extends AppCompatActivity {

    Button myButton;
    public static int OVERLAY_PERMISSION_REQ_CODE = 2;

    LinearLayout rootContainer_LL;
    LinearLayout scrollViewWrapperItems_LL;

    MyReactView myReactView;

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

        rootContainer_LL = new LinearLayout(this);

        myButton = new Button(this);
        myButton.setText("REV _Button");
        myButton.setOnClickListener(v -> viewOnClick());

        rootContainer_LL.addView(myButton);
        setContentView(rootContainer_LL);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
            }
        }

        myReactView = new MyReactView(this);
    }

    void viewOnClick() {
        rootContainer_LL.addView(myReactView.reactJsView());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (!Settings.canDrawOverlays(this)) {
                    // SYSTEM_ALERT_WINDOW permission not granted...
                }
            }
        }
    }
}  

Get the React view :

public class MyReactView {

    private Context context;
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    public MyReactView(Context context) {
        this.context = context;

        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(((Activity) context).getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.BEFORE_CREATE)
                .build();
    }

    public View reactJsView() {
        Bundle initialProperties = new Bundle();
        initialProperties.putString("var_1", "Im the first var");

        mReactRootView = new ReactRootView(context);
        mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", initialProperties);

        return mReactRootView;
    }

}  

Then MainApplication

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost =
            new ReactNativeHost(this) {
                @Override
                public boolean getUseDeveloperSupport() {
                    return BuildConfig.DEBUG;
                }

                @Override
                protected List<ReactPackage> getPackages() {
                    @SuppressWarnings("UnnecessaryLocalVariable")
                    List<ReactPackage> packages = new PackageList(this).getPackages();
                    // Packages that cannot be autolinked yet can be added manually here, for example:
                    // packages.add(new MyReactNativePackage());
                    // return packages;

                    packages.add(new CustomToastPackage());

                    Log.v("MyApp", "APP CALL FUNCS");

                    return packages;
                }

                @Override
                protected String getJSMainModuleName() {
                    return "index";
                }
            };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}  

Then I try adopting the implementation as directed in The Toast Module

ToastModule

public class ToastModule extends ReactContextBaseJavaModule {
    private static ReactApplicationContext reactContext;

    private static final String DURATION_SHORT_KEY = "SHORT";
    private static final String DURATION_LONG_KEY = "LONG";

    ToastModule(ReactApplicationContext context) {
        super(context);
        reactContext = context;
    }

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

    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
        constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
        return constants;
    }

    @ReactMethod
    public void showJ(String message, int duration) {
        Toast.makeText(getReactApplicationContext(), message, duration).show();
    }
}  

CustomToastPackage

public class CustomToastPackage implements ReactPackage {

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

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

        modules.add(new ToastModule(reactContext));

        return modules;
    }
}  

The Javascript call

import {NativeModules} from 'react-native';
module.exports = NativeModules.ToastExample;  

then . . .

import ToastExample from './ToastExample';

ToastExample.showJ('Awesome', ToastExample.SHORT);  

UPDATE

The full javascript implementation :

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, Text, View, TouchableOpacity} from 'react-native';

import {name as appName} from './app.json';

import ToastExample from './ToastExample';

class HelloWorld extends Component {

    async sayHiFromJava() {
        ToastExample.showJ('Awesome', ToastExample.SHORT);
    }

    render() {
        return (
            <View style={
                styles.container
            }>
                <TouchableOpacity style={
                        styles.btnStyleH
                    }
                    onPress={
                        this.sayHiFromJava
                }>
                    <View>
                        <Text style={
                            styles.btnStyle
                        }>...PUSH</Text>
                    </View>
                </TouchableOpacity>
            </View>
        );
    }
}
var styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'flex-start',
        flexDirection: 'row'
    },
    btnStyle: {
        fontSize: 10,
        justifyContent: 'flex-start'
    }
});

AppRegistry.registerComponent(appName, () => HelloWorld);

then : ToastExample.js

import {NativeModules} from 'react-native';
module.exports = NativeModules.ToastExample;

are you add a file named "ToastExample.js" and add these lines into.

 import {NativeModules} from 'react-native'; module.exports = NativeModules.ToastExample;

and then call the "ToastExample.js" file from your main js file by means of these lines:

 import ToastExample from './ToastExample'; ToastExample.showJ('Awesome', ToastExample.SHORT);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM