Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native - Headless JS example

Tags:

react-native

The react native documentation about this seems more than incomplete. I was following this guide which doesn't seem to lead me anywhere:

https://facebook.github.io/react-native/releases/next/docs/headless-js-android.html#headless-js

Where am I supposed to put the .java file? How am I supposed to start the task?

like image 256
Alex Avatar asked Jan 20 '17 15:01

Alex


People also ask

What is headless JS in react native?

Headless JS is a way to run tasks in JavaScript while your app is in the background. It can be used, for example, to sync fresh data, handle push notifications, or play music.

Is it possible to run a react native app in the background?

React Native background service library for running background tasks forever in Android & iOS. Schedule a background job that will run your JavaScript when your app is in the background or foreground.

Is react JS headless?

React is a JavaScript library for building user interfaces. It is maintained by Facebook and a community of individual developers and companies. Strapi is an open-source headless CMS built with React. js.

Is react native multithreaded?

React Native is single-threaded in nature. In its rendering process, rather than have multiple processes occur at the same time (multithreading), other components have to wait when one component is being rendered.


1 Answers

I had the same problem as you did. I'm new to native Android dev and I followed the docs, but they didn't work for me. Turns out I misunderstood and thought that I can start the actual task FROM my react native code. It doesn't work that way, though. You write the JavaScript code you want to run when the task is started, but you need to start that task from native code. So, steps you did already are setting up the task, but nothing is telling them to start.

I'll use my project as an example:

In my JavaScript:

    /* 
      This code basically registers WHAT javascript code
      I want to call when the 'disconnect' service is started
    */

    const disconnectTask = () => async () => {
      if (connectionIsActive) {
        user.goOffline();
      }
    };

    AppRegistry.registerHeadlessTask('disconnect', disconnectTask);

Then I created the java file here:

projectroot/android/app/src/main/java/com/mycompany/app/ForceOfflineService.java

package com.mycompany.app;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
import com.facebook.react.bridge.WritableMap;
import javax.annotation.Nullable;

public class ForceOfflineService extends HeadlessJsTaskService {
  @Override
  @Nullable
  protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
      Bundle extras = intent.getExtras();
      // WritableMap data = extras != null ? Arguments.fromBundle(extras) : null;
      
      // ---- EDIT ---- the line above no longer works, since null is not an accepted value anymore.
      WritableMap data = extras != null ? Arguments.fromBundle(extras) : Arguments.createMap();

      // Make sure that the string below ("disconnect" in this case)
      // matches the string used to register the task in your JS

      return new HeadlessJsTaskConfig(
              "disconnect",
              data,
              5000);
  }
}

then inside your android manifest (mine is here: projectroot/android/app/src/main/AndroidManifest.xml) you must register the service inside the application tag

<manifest>
  <application>

    <!-- other existing configuration -->

    <service android:name=".ForceOfflineService" />
  </application>
</manifest>

Lastly, you need to use the native code to start the service. In my MainActivity.kt I start the service when the onStop lifecycle hook is called:

 override fun onStop() {
    super.onStop()

    Handler(Looper.getMainLooper()).postDelayed(Runnable {
      val service = Intent(applicationContext, ForceOfflineService::class.java)
      applicationContext.startService(service)
    }, IDLE_TIME_BEFORE_DISCONNECT)
  }

and that's it!

like image 129
tkd_aj Avatar answered May 08 '23 18:05

tkd_aj