Run React Native code while application is closed
<h2>Problem</h2>

<p>I have been trying to create a React Native application used to catch phone calls and send the numbers to an API. I have created a working native module for catching the phone calls in Java. I have also managed to send an event to my JavaScript code and managed to catch this event and log the number through console.log in JavaScript.</p>

<p>Now my problem is that i need the application to work even if the application is closed (in background). I have not been able to find any way to wake the react native code with a Java module or to run the Javascript without starting the application. </p>

<hr>

<h2>Code</h2>

<p>This is my BroadcastReciver:</p>

<pre><code>package com.wavyassist;

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 CallCatcher extends BroadcastReceiver {

private CallCatcherModule module;

public CallCatcher (){
    this.module = CallCatcherModule.getInstance();
}

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
    {
        String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
        Toast.makeText(context, "Call from:" +incomingNumber, Toast.LENGTH_LONG).show();
        module.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();
        }
    }
}
</code></pre>

<p>This is my Module:</p>

<pre><code>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.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

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

import javax.annotation.Nullable;

import java.util.Map;

public class CallCatcherModule extends ReactContextBaseJavaModule {

    private ReactContext reactContext;
    private static CallCatcherModule instance;

    public static CallCatcherModule getInstance(ReactApplicationContext     reactContext){
        if (instance == null) {
            instance = new CallCatcherModule(reactContext);
        }
        return instance;
    } 

    private CallCatcherModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    } 

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

    public static CallCatcherModule getInstance(){
        return instance;
    }  

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


    private void sendEvent(ReactContext reactContext,
                            String eventName,
                            @Nullable WritableMap params) {
        reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit(eventName, params);
        Log.d("CallCatcherModule", "Event Emitted");
    }
}
</code></pre>

<p>These classes will always send the number when call is catched. To receive the event in javascript I am currently using this working example. (this code only works if i restart the entire application.)</p>

<pre><code>"use strict";


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

var emitter;

class RegDone extends Component {
  constructor(props) {
    super(props);
    this.handleCall = this.handleCall.bind(this);
    this.changeListenerState = this.changeListenerState.bind(this);
    this.state = {test: ''};
  }

  componentWillMount(){
    console.log('RecivingCall: Starting Listener');
    emitter = DeviceEventEmitter.addListener('CallRecevied', this.handleCall);
  }

  componentWillUnmount(){
    console.log('RecivingCall: Stoping Listener')
    emitter.remove();
    this.setState({text: ''});
  }

  handleCall(Event){
    console.log('RecivingCall: Call Recevied! Number: ' + Event.Number);
    this.setState({test:  Event.Number});
  }

  render() {
    return (
      &lt;View style={styles.container}&gt;
          &lt;Text &gt;
            {this.state.test}
          &lt;/Text&gt;
      &lt;/View&gt;
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  button: {
    backgroundColor: '#aaaaaa',
    padding: 20,
  },
});


module.exports = RegDone;
</code></pre>

<hr>

<h2>What I have tried</h2>

<p>I have tried to write the JS code in a separate class that is not a view. This I failed with. There were no way I could contact the methods in the new class and ended up writing the code in a view class again. </p>

<p>I have also tried to start and stop the DeviceEventEmitter on button press but this simply did nothing.(not sure why!)  </p>

<hr>

<h2>Summary</h2>

<p>The problem seems to be that the JavaScript is only available when the application is up and running and the specific view containing the JS code is on display.</p>

<p>If anyone have any information regarding how you run React native JS code while the application is closed or if you know a way to start the application up when an event is triggered. I would very much appreciate the information. </p>