Subscribe now

Using Android Native Modules [10.10.2017]

In today's episode we will use something from our Android code in our React Native app.

This might be something you would want: use something native in your app. How can we do that? It's not hard!

Luckly, React Native has an API to handle this. We can do this in three steps:

  • Create our Native Module
  • Register the module
  • Wrap this module in the JavaScript code

Creating our Project

Let's create a React Native project that will use the native module.

react-native init UsingNativeModules

Ok! Project created!

Inside the React Native project, we have an Android project and a iOS project. We will use the Android project.

Creating our Native module

We will open the Android project using Android Studio.

The native functionality we will use is to keep the screen awake. This is something easy to implement in pure Java/Android code.

We start by creating a class and extending to ReactContextBaseJavaModule. Our module name will be ViewUtil. And I will call the class ViewUtilModule.

...
public class ViewUtilModule extends ReactContextBaseJavaModule {
...

In our module, we need to implement a method called getName. This represents the class, which will be called in JavaScript. In our case, our native module will be called ViewUtl. So, we can call this in JavaScript by calling React.NativeModules.ViewUtil.

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

Each method that will be visible in the JavaScript code should have a @ReactMethod annotation.

We will have two methods, one for keep the screen awake, and another to remove this. Let's have the reactContext as a field in the class, just in case we might want to use it in the future.

Now, let's create our two methods. To keep the screen awake, we need to get the current activity and add a flag to this activity by using WindowsManager. Keeping the screen awake means adding the FLAG_KEEP_SCREEN_ON, and removing that makes the screen just like normal.

...
public class ViewUtilModule extends ReactContextBaseJavaModule {

    ReactApplicationContext reactContext;

    public ViewUtilModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

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

    @ReactMethod
    public void keepScreenAwake() {
        getCurrentActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                getCurrentActivity().getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            }
        });
    }

    @ReactMethod
    public void removeScreenAwake() {
        getCurrentActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                getCurrentActivity().getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            }
        });
    }

Now, we have our two methods implemented.

Registering the module

Let's create anoter class that will implement the ReactPackage interface.

...
public class ViewUtilPackage implements ReactPackage {
...

We will call this ViewUtilPackage. Implemeting this interface means we need to implement two methods: createNativeModules and createViewManagers.

To register the module, we use the method createNativeModules.

With this, we will be able to call the methods from the Java code inside our JavaScript code.

Let's start by implementing this method. We will have a list of modules and we will add to this list the module we have created, the ViewUtilModule.

@Override
public List<NativeModule> createNativeModules(
        ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new
            ViewUtilModule(reactContext));

    return modules;
}

For the createViewManagers method, we will just return an empty list for Collections.

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext
        reactContext) {
    return Collections.emptyList();
}

So, this will be the code for our React Package.

package com.usingnativemodules;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by franzejr on 10/5/17.
 */

public class ViewUtilPackage implements ReactPackage {

    @Override
        public List<NativeModule>
        createNativeModules(ReactApplicationContext reactContext) {
            List<NativeModule> modules = new ArrayList<>();

            modules.add(new ViewUtilModule(reactContext));
            return modules;
        }

    @Override
        public List<ViewManager>
        createViewManagers(ReactApplicationContext
                reactContext) {
            return Collections.emptyList();
        }
}

We need add to this package to our MainApplication.java file, in the method getPackages. This file is also located inside our Android project.

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
            new ViewUtilPackage()
      );
    }
  };

This is everything we need to do on the Android side.

Using the Android code in our JavaScript project

Now we have implemented everything on the Android side. It's time to use this in our React Native project.

Let's create the file that gets our Android code.

vim ViewUtilModule.js

We will use NativeModules from react-native.

/**
 * This exposes our Android code into our RN project
 */

import { NativeModules } from "react-native";
module.exports = NativeModules.ViewUtil;

And we can import this in any other file.

...
import ViewUtil from "./ViewUtilModule";
...

In our componentDidMount method, we will enable screenAwake.

componentDidMount() {
    if (Platform.OS != "ios") {
        ViewUtil.keepScreenAwake();
    }
}

Take a look: here we are using the same method we declared in our Java code. Now, something from Java can be executed from here! Sweet!

Testing it

So, I have the app running. I've enabled live reload if we want to change something and see the changes quickly.

I've disabled the Stay awake options in the Developer options, and I set the time screen sleep to 15 seconds.

As you can see, this time I'm talking the screen is already off. We should open our app and the screen should be awake. Let's do that.

Ok, now our app is up. Let's count.. 1..2..3. Our screen should be up everytime. Yes. It seems it worked, nice! Now, we will disable the screenAwake, by using our method removeScreenAwake.

Ok, now, let's wait a couple seconds and see what happens with our screen. It should power off. Let's wait a bit more... Nice. It worked!

Summary

Today we saw how to create a native module in React Native using Android/Java code. As a native functionality we saw how to keep the screen awake.

Resources