nipek
nipek

Reputation: 850

Access methods from .jar file in react native(android)

I'd like to import a module written natively (java, Android) into my React Native sources, in JS.

Upvotes: 0

Views: 769

Answers (1)

Geronimo
Geronimo

Reputation: 238

To access your functionality implemented in java you have to create a bridge. You can see the most recent instructions in the RN documentation site*.

The steps, assuming React Native 0.61, for a hello world, to be implemented in the android project inside the react native app directory (android directory): 1) First you create a simple POJO class to be returned to the react native context:

class MyData{
    private int timeSpentSleeping;

    public int getTimeSpentSleeping() {
        return timeSpentSleeping;
    }

    public void setTimeSpentSleeping(int timeSpentSleeping) {
        this.timeSpentSleeping = timeSpentSleeping;
    }

    @NonNull
    @Override
    public String toString() {
        Gson gson = new Gson();
        String json = gson.toJson(this);
        return json;
    }

    static MyData build(final int timeSpentSleeping){
        MyData newInstance = new MyData();
        newInstance.timeSpentSleeping = timeSpentSleeping;
        return newInstance;
    }
}

And the react native module that do something and return objects of this class as javascript Promises:

public class HelloPromiseModule extends ReactContextBaseJavaModule {
    public HelloPromiseModule(@NonNull ReactApplicationContext reactContext) {
        super(reactContext);
    }

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

    @ReactMethod
    public void foobar(Promise promise){
        Random r = new Random();
        final int timeToSleep = r.nextInt(1000);
        runThreadAndCallPromiseToJavascript(timeToSleep, promise);
    }
    //Cria um thread pra executar algo em paralelo
    private void runThreadAndCallPromiseToJavascript(final int timeToSleep,final Promise promise){
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(timeToSleep);
                    MyData result = MyData.build(timeToSleep);
                    promise.resolve(result.toString());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    promise.reject(e);
                }
            }
        });
        t.run();
    }
}

Now, we create the React Native Package (that is different from java packages):

public class HelloWorldPackage implements ReactPackage{
    @NonNull
    @Override
    public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(
                new HelloPromiseModule(reactContext));
    }

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

The last step in the android version of your react native app is to register your HelloWorldPackage: In the MainApplication.java inside your android project, inside the getPackages(), in the list of packages (new PackageList(this)...):

packages.add(new HelloWorldPackage());

Something like that:

protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
          packages.add(new HelloWorldPackage());
          return packages;
        }

Now, to get your native class in the javascript world:

import {
  NativeModules,
} from 'react-native';
...
const {HelloPromise} = NativeModules;

Your native class is accessible from the variable HelloPromise. You can get the result of HelloPromise.foobar() with something like this, in the react native side of your code:

async function handleHelloPromisesPress() {
   let result = await HelloPromise.foobar();
   console.log(result);
}

You may notice that 'result' is a json whose structure is equal to the POJO class we created in the beginning.

Upvotes: 1

Related Questions