Jared
Jared

Reputation: 31

Why is my reactContext variable still null?

I am trying to send a message to react native when I receive a text message. I really need help with this and I have no clue what I am doing wrong!

This is my Module that I created to manage sending events to react native.

public class SendEventModule extends ReactContextBaseJavaModule implements ActivityEventListener {

    private static ReactApplicationContext reactContext;
    //private static ReactInstanceManager sReactInstanceManager = null;


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


    public SendEventModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        reactContext.addActivityEventListener(this);
    }

    public static void test(String event, WritableNativeMap params) {
        Log.e("TEST_ERROR", "This is just a test");
        //final ReactContext context = sReactInstanceManager.getCurrentReactContext();
        sendEvent((ReactApplicationContext) reactContext, event, params);
    }

    private static void sendEvent(ReactApplicationContext reactContext,String event, WritableNativeMap params) {
        Log.e("TEST_ERROR", "we made it to send event");
        //context = (ReactApplicationContext) this.reactContext;
        //ReactContext currentContext = getReactApplicationContext();

        if(reactContext != null) {

            reactContext.getJSModule(RCTDeviceEventEmitter.class).emit(event, params);

        } else {
            try {
                reactContext.getJSModule(RCTDeviceEventEmitter.class).emit(event, params);
            }catch(Exception e) {
                Log.e("TEST_ERROR", e.getMessage());
            }
            Log.e("TEST_ERROR", "React Context is not defined");

        }

    }

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {}

    @Override
    public void onNewIntent(Intent intent){}


}

This is my SMS receiver where I am attempting to emit my event to react native


public class SmsBroadcastReceiver extends BroadcastReceiver {

    private static ReactApplicationContext reactContext;

    public void onReceive(Context context, Intent intent) {

        Bundle intentExtras = intent.getExtras();
        Toast.makeText(context, "Message Received Bitch!", Toast.LENGTH_SHORT).show();

        //WritableMap params = Arguments.createMap();
        //params.putString("eventProperty", "someValue");

        WritableNativeMap params = new WritableNativeMap();
        params.putString("eventProperty", "someValue");


        try {
            SendEventModule.test("EventReminder", params);

        } catch (Exception e) {
         Log.e( "EVENT_ERROR", e.getMessage() );
        }


    }


}

This is my ERROR and it is clear the reactContext is not defined and I have no idea why

2019-10-14 12:44:56.604 17861-17861/com.test E/TEST_ERROR: Attempt to invoke virtual method 'com.facebook.react.bridge.JavaScriptModule com.facebook.react.bridge.ReactApplicationContext.getJSModule(java.lang.Class)' on a null object reference

This is the code for my react native screen

import React from "react";
import {
  Container,
  Header,
  Content,
  Textarea,
  Form,
  Button,
  Text,
  Left,
  Body,
  Right,
  Icon,
  Title,
  List,
  ListItem,
  Radio,
  CheckBox,
  Footer,
FooterTab,
Item,
Input } from "native-base";
import { GiftedChat } from 'react-native-gifted-chat';
import SendSMS from 'react-native-sms-x';
import { NativeEventEmitter, NativeModules, DeviceEventEmitter, TouchableOpacity, Image } from 'react-native';
import { Col, Row, Grid } from "react-native-easy-grid";
//import { setJSExceptionHandler, getJSExceptionHandler } from 'react-native-exception-handler';



class NewMessageScreen extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      messages: [],
      data: props.navigation.state.params.data
    };
  }

  componentDidMount() {

    this.setState({
      messages: [
        {
          _id: 1,
          text: 'Hello developer',
          createdAt: new Date(),
          user: {
            _id: 2,
            name: 'React Native',
            avatar: 'https://placeimg.com/140/140/any',
          },
        },
      ],
    });

    const eventEmitter = new NativeEventEmitter(NativeModules.SendEventModule);

    eventEmitter.addListener('EventReminder', (event) => {
       console.log(event.eventProperty); // "someValue"
    });


  }




  onSend(messages = []) {
    this.setState(previousState => ({
      messages: GiftedChat.append(previousState.messages, messages),
    }));

    SendSMS.send(1, this.state.data.number, messages[0].text,
      (msg)=>{
        alert(JSON.stringify(msg));
      }
    );

  }


  headerTitle() {
    //alert(JSON.stringify(this.state.data));
    if(this.state.data) {
      if (typeof this.state.data.displayName !== 'undefined') {
        return this.state.data.displayName;

      } else {
        return this.state.data.first_name + " " + this.state.data.last_name;
      }
    } else {
      return "Group Text";
    }
  }

  render() {
    return (
      <Container>
      <Header style={{ backgroundColor: '#234561'}} transparent>
        <Body>
          <Title style={{ justifyContent: 'center', width: '100%'}}>{ this.headerTitle() }</Title>
        </Body>
      </Header>

        <Row size={1} style={{ backgroundColor: "#234561" }}>
          <Col>
            <TouchableOpacity
               style={{
                   borderWidth:1,
                   borderColor:'rgba(0,0,0,0.2)',
                   alignItems:'center',
                   justifyContent:'center',
                   width:65,
                   height:65,
                   backgroundColor:'#fff',
                   borderRadius:50,
                   overflow: 'hidden',
                   poisition: 'absolute',
                   left: '50%',
                   marginLeft: -33,
                   top: '50%',
                   marginTop: -33,
                   elevation: 10
                 }}
             >
               <Image style={{ height: '100%', width: '100%'}} source={{ uri: 'https://icon-library.net/images/default-user-icon/default-user-icon-14.jpg' }} />
             </TouchableOpacity>
          </Col>
          <Col>
            <TouchableOpacity
               style={{
                   borderWidth:1,
                   borderColor:'rgba(0,0,0,0.2)',
                   alignItems:'center',
                   justifyContent:'center',
                   width:90,
                   height:90,
                   backgroundColor:'#fff',
                   borderRadius:50,
                   overflow: 'hidden',
                   left: '50%',
                   marginLeft: -45,
                   top: '50%',
                   marginTop: -45,
                   elevation: 10

                 }}
             >
               <Image style={{ height: '100%', width: '100%'}} source={{ uri: 'https://icon-library.net/images/default-user-icon/default-user-icon-14.jpg' }} />
             </TouchableOpacity>
           </Col>
          <Col>
            <TouchableOpacity
               style={{
                   borderWidth:1,
                   borderColor:'rgba(0,0,0,0.2)',
                   alignItems:'center',
                   justifyContent:'center',
                   width:65,
                   height:65,
                   backgroundColor:'#fff',
                   borderRadius:50,
                   overflow: 'hidden',
                   poisition: 'absolute',
                   left: '50%',
                   marginLeft: -33,
                   top: '50%',
                   marginTop: -33,
                   elevation: 10
                 }}
             >
               <Image style={{ height: '100%', width: '100%'}} source={{ uri: 'https://icon-library.net/images/default-user-icon/default-user-icon-14.jpg' }} />
             </TouchableOpacity>
          </Col>
        </Row>

        <Row size={4}>
          <GiftedChat
            messages={this.state.messages}
            onSend={messages => this.onSend(messages)}
            user={{
              _id: 1,
            }}
          />
        </Row>
      </Container>
    );
  }

}

export default NewMessageScreen;

PLEASE HELP!!!

Upvotes: 1

Views: 2953

Answers (2)

Jared
Jared

Reputation: 31

I solved this problem by registering the Module; this happens in the createNativeModules of an apps package. If a module is not registered it will not be available from JavaScript and it will not have access to ReactApplicationContext!!!


public class SendEventPackage 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 SendEventModule(reactContext));

        return modules;
    }

}

After creating this, The package needs to be provided in the getPackages method of the MainApplication.java file.

        @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 SendEventModule(this)); // THIS IS THE WRONG WAY
            packages.add(new SendEventPackage()); // <-- Add this line with your package name.

            return packages;
        }

Upvotes: 2

Traendy
Traendy

Reputation: 1503

You have a Constructor in your SendEventModule

public SendEventModule(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
    reactContext.addActivityEventListener(this);
}

But you call your methods with static access, without intatiating your SentEventModule first via the constructor. In your methods you are trying to access reactContext, which has never been set.

In Java a variable has to be set to be not null. e.G

String text;
// text == null
text = "awesome";
// text == "awesome";

Maybe these two links will help you to solve your issues: https://gist.github.com/renganatha10/96ce8c845d981008d2a76da756954b25 How to access Activity from a React Native Android module?

Further reading on static: https://www.javatpoint.com/static-keyword-in-java

Upvotes: 0

Related Questions