0

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;

1 Answer 1

1

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);

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the reply, but I already had that added. I have included the full Javascript call in an update in the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.