Eddie Owens
Eddie Owens

Reputation: 143

React native events fail to emit when called from IntentService

For some reason when emitting an event via an IntentService nothing happens on the Javascript side. Here's what I'm doing:

  1. Create an IntentService with an onHandleIntent method like so:

    @Override
    protected void onHandleIntent(@Nullable final Intent intent) {
      if (intent != null) {
        logger.info("Broadcasting event");
        intent.setAction(ACTION);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
      }
    }
    
  2. Register the IntentService to the com.google.android.gms.location.GeofencingClient:

    Intent intent = new Intent(getReactApplicationContext().getBaseContext(), BoundaryEventIntentService.class);
    this.mBoundaryPendingIntent = PendingIntent.getService(getReactApplicationContext().getBaseContext(), 0, intent, PendingIntent.
            FLAG_UPDATE_CURRENT);
    
  3. Create the BroadcastReceiver for the IntentService to broadcast messages to:

    public class GeofenceEventBroadcastReceiver extends BroadcastReceiver {
    
    @Override
    public void onReceive(Context context, Intent intent) {
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            // handle errors
        }
        switch (geofencingEvent.getGeofenceTransition()) {
            case Geofence.GEOFENCE_TRANSITION_ENTER:
                Log.i(TAG, "Enter geofence event detected. Sending event.");
                WritableArray writableArray = Arguments.createArray();
                for (Geofence geofence : geofencingEvent.getTriggeringGeofences()) {
                    writableArray.pushString(geofence.getRequestId());
                }
                sendEvent(ON_ENTER, writableArray);
                break;
            // handle other events e.g. GEOFENCE_TRANSITION_EXIT
          }
       }
    }
    
  4. And finally my sendEvent method:

    private void sendEvent(String event, Object params) {
      Log.i(TAG, "Sending events " + event);
      getReactApplicationContext()
          .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
          .emit(event, params);
      Log.i(TAG, "Sent events");
    }
    

My BroadcastReceiver is an inner class on my ReactContextBaseJavaModule so it has access to my react application context and the sendEvent method. Everything triggers successfully except the javascript side of this does not receive the event. I realize this is quite a bit of code and I may not have included all of the needed context. The library can be found here if more context is needed.

Upvotes: 3

Views: 677

Answers (1)

sangeeth_vvs
sangeeth_vvs

Reputation: 93

A possible reason would be you are using intent service, which will be affected by doze mode. Update to use Job Intent Service instead of intent service.

https://developer.android.com/reference/android/support/v4/app/JobIntentService

Android background location limits In order to preserve battery, user experience, and system health, background apps receive location updates less frequently when used on a device running Android 8.0. This behavior change affects all apps that receive location updates, including Google Play services.

These changes affect the following APIs:

Fused Location Provider (FLP) Geofencing GNSS Measurements Location Manager Wi-Fi Manager

Read this link for changes that are done in 8.0

https://developer.android.com/about/versions/oreo/android-8.0-changes

Note: IntentService is a service, and is therefore subject to the new restrictions on background services. As a result, many apps that rely on IntentService do not work properly when targeting Android 8.0 or higher. For this reason, Android Support Library 26.0.0 introduces a new JobIntentService class, which provides the same functionality as IntentService but uses jobs instead of services when running on Android 8.0 or higher.

Upvotes: 1

Related Questions