简体   繁体   中英

How do I access ReactContext from Java code in React Native?

I an trying to create an application thet will catch the incoming calls to the cellphone using a BroadcastReciver. From my BroadcastReciver i whould like to sent the number as an event to my JS file using this method.

I have checked that my Java code is working and is catching the calls and number but my application craches with the error that mentions that the react context is null. I am guessing that this is because the manifest (or something) is creating a new instance of the class when the event from the android system is catched and that the new instance does not have a ReactContext. Is there any way to access the ReactContext from the Java code or send a ReactContext to the BroadcastReciver through the manifest?

This is my BroadcastReciver:

package com.bridgetest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.JavaScriptModule;


import android.widget.Toast;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;

import javax.annotation.Nullable;

/**
 * Created by Erik on 2016-04-06. 
 */
public class BroadcastReceiverCustom extends BroadcastReceiver {

    ReactContext reactContext;

    public BroadcastReceiverCustom (){
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if             (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
            // This code will execute when the phone has an incoming call

            // get the phone number
            String incomingNumber =     intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
            Toast.makeText(context, "Call from:" +incomingNumber, Toast.LENGTH_LONG).show();
            sendCallEvent(incomingNumber);

        } else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
                TelephonyManager.EXTRA_STATE_IDLE)
                || intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
                    TelephonyManager.EXTRA_STATE_OFFHOOK)) {
            // This code will execute when the call is disconnected
            Toast.makeText(context, "Detected call hangup event", Toast.LENGTH_LONG).show();
        }
    }

    public void sendCallEvent(String incomingNumber){
            WritableMap params = Arguments.createMap();
            params.putString("Number", incomingNumber);
            sendEvent("CallRecevied", params);
    }


    private void sendEvent(String eventName,
                          @Nullable WritableMap params) {
        reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit(eventName, params);
    }
}

As Fury's solution did not work for me(got "cannot find symbol" for getApplication()) in the broadcast receiver, i tried applying a similar logic with what i knew is working. So:

import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.ReactApplication;
...
// context - is the context you get from broadcastreceivers onReceive
ReactApplication rnApp = (ReactApplication) context.getApplicationContext();

rnApp.getReactNativeHost().getReactInstanceManager()
                                .getCurrentReactContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                                .emit("test", Arguments.createMap());

This worked for me.

我遇到了同样的问题,正在使用它。

((MainApplication)getApplication()).getReactNativeHost().getReactInstanceManager().getCurrentReactContext()

I solved the problem. I created a ReactContextBaseJavaModule with a singleton pattern and got access to ReactContext through it (This might be a huge "nono").

If there is another smarter way to solve this problem, please inform me.

You can access reactContext like this:

import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;

ReactInstanceManager reactInstanceManager = getReactNativeHost().getReactInstanceManager();
      ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
      if(reactContext != null) {
          // Use reactContext here
      } else {
          reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
              @Override
              public void onReactContextInitialized(ReactContext context) {
          // Use context here
          reactInstanceManager.removeReactInstanceEventListener(this);
              }
          });
      }

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