React-Native Android ReactContext返回null

时间:2016-01-27 15:50:45

标签: android react-native

由于React-Native AppState API仅适用于iOS,因此我正在为我的应用的Android端编写appState事件发射器。在Java端的应用程序MainActivity中,我希望从onResumeonPause函数发出信号,通过网桥告诉JS端我的应用程序位于前台背景

目前,我可以最小化我的应用(并返回设备上的主屏幕)并正确发出背景事件。然而,当我恢复我的应用程序时,什么都没有被解雇...当应用程序最初打开时也没有被触发。

我已将此缩小到这样的事实:在这些情况下mReactInstanceManager.getCurrentReactContext()由于某种原因而为空......

以下是MainActivity.java的代码:

@Override
protected void onPause() {
    super.onPause();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onPause();

        //send the appState back to JS
        Log.d("REACT_STATE", "Paused");  //this always fires
        if(mReactInstanceManager.getCurrentReactContext()!=null) {
            WritableMap params = Arguments.createMap();
            params.putString("currentAppState", "background");
            sendEvent(mReactInstanceManager.getCurrentReactContext(), "appStateChange", params);
        }
    }
}

@Override
protected void onResume() {
    super.onResume();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onResume(this, this);

        //send the appState back to JS
        Log.d("REACT_STATE", "Resumed"); //this also always fires
        if(mReactInstanceManager.getCurrentReactContext()!=null) {
            WritableMap params = Arguments.createMap();
            params.putString("currentAppState", "foreground");
            sendEvent(mReactInstanceManager.getCurrentReactContext(), "appStateChange", params);
        }
    }
}

这是发射器代码:

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

事情的JS方面设置正常并且正常 - 如果有帮助,我可以提供此代码。我很确定我的问题就在于这一方面。我想在错误的时间发出这个吗?我需要把它移到其他地方吗?任何建议都非常感谢!

3 个答案:

答案 0 :(得分:2)

好的,我已经设法对此进行排序。我创建了一个新的插件包AppStateAndroid,它会回发给JS​​。这是在应用程序生命周期中的正确时间添加的,并且运行良好。我要将代码发布到GitHub(http://github.com/scgough),但对于那些想知道你在这里的人来说:

public class AppStateAndroidPlugin extends ReactContextBaseJavaModule implements Application.ActivityLifecycleCallbacks {

private static final String PLUGIN_NAME = "AppStateAndroid";

private ReactContext mReactContext;

protected Activity activity = null;

protected Activity getActivity(){
    return this.activity;
}

public AppStateAndroidPlugin(ReactApplicationContext reactContext, Activity activity) {
    super(reactContext);

    this.mReactContext = reactContext;

    this.activity = activity;
    this.activity.getApplication().registerActivityLifecycleCallbacks(this);
}

private void sendEvent(ReactContext reactContext,
                       String eventName,
                       @Nullable WritableMap params) {

    Log.d(PLUGIN_NAME, "Sending Event"+params.toString());
    reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit(eventName, params);
}
...
@Override
public void onActivityResumed(Activity activity) {
    Log.d(PLUGIN_NAME, "Resumed");
    if(mReactContext!=null) {
        WritableMap params = Arguments.createMap();
        params.putString("currentAppState", "active");
        sendEvent(mReactContext, "appStateChange", params);
    }
}

@Override
public void onActivityPaused(Activity activity) {
    Log.d(PLUGIN_NAME, "Paused");
    if(mReactContext!=null) {
        WritableMap params = Arguments.createMap();
        params.putString("currentAppState", "background");
        sendEvent(mReactContext, "appStateChange", params);
    }
}
...
@Override
public void onActivityDestroyed(Activity activity) {
    Activity myActivity = this.getActivity();
    if (activity == myActivity){
        myActivity.getApplication().unregisterActivityLifecycleCallbacks(this);
    }
}

@Override
public String getName() {
    return PLUGIN_NAME;
}
}

在主要活动中,您需要一个包文件:

mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(getApplication())
            .setBundleAssetName("index.android.bundle")
            .setJSMainModuleName("index.android")
            .addPackage(new MainReactPackage())
            .addPackage(new AppStateAndroidPluginPackage(this))
            ...

答案 1 :(得分:0)

对于任何想要从Activity获取ReactContext实例的方法,请使用

 this.getReactNativeHost().getReactInstanceManager().getCurrentReactContext();

而不是

 this.getReactInstanceManager().getCurrentReactContext();

虽然我不明白为什么......

答案 2 :(得分:0)

GitHub: Is there any callback for android when ReactContext is created in MainAcitivity? #3887

您可以通过监听onReactContextInitialized回调来避免这种情况。

if (null!=str  && !str.isEmpty()){
   Log.d(TAG,"String ID is not Null ");                 
} else {
   Log.d(TAG,"String ID is Null ");            
}

创建ReactContext后,将通知回调:

@Override
public void onResume() {
    super.onResume();
    getReactInstanceManager().addReactInstanceEventListener(this);
}  

@Override
public void onPause() {
    super.onPause();
    getReactInstanceManager().removeReactInstanceEventListener(this);
}  

OR:

@Override
public void onReactContextInitialized(ReactContext context) {
    Log.d(TAG, "Here's your valid ReactContext");
}