サイト名変更・お引越しのお知らせ

【Android・Java】React NativeでNative Modulesを実装する方法を解説

React NativeでAndroid向けにJavaを用いて、Native Modulesを実装する方法を解説します。

モグモグさん

出来るだけ分かりやすく解説していきます。

この記事でわかること
  • Native Modulesがわかる
  • Javaを用いてカスタムのNative Modulesを作成することができる

バージョン
  • React 17.0.2
  • React Native 0.65.1

モグモグさん

Kotlinで実装する方法についてはこちらで解説しています。

【Android・Kotlin】React NativeでNative Modulesを実装する方法を解説

Native Modulesとは?

Native Modulesについて簡単に解説します。

モグモグさん

すでに理解している方はスキップしてください。

Native Modulesとは、React Nativeで用意されていない機能をネイティブで実装するための機能です。

アプリの要件によって、React Nativeがもともと用意していない機能を足したり、パフォーマンスの観点等でネイティブで実装すべき箇所をNative Modulesを使って実装したりすることが多いです。

React Nativeでも多くのことがすでにできますが、Native Modulesを使うことで幅が広がります

  • iOS: Objective-CSwiftどちらでも実装可能
  • Android: JavaKotlinどちらでも実装可能

本記事では紹介しませんが、UIに関連するものは、Native UI Componentsを利用します。

モグモグさん

事前準備(ベースのアプリを作成)

まずは、React Nativeでアプリを作成しましょう。

この記事では、NativeModuleExampleというプロジェクトを作成しました。

モグモグさん

すでに作成済みの方はスキップでOKです!

こちらの記事も参考にしてください。

ReactNative 【ReactNative入門 】Macで開発環境を作って始める

Native Modulesの作成

それでは、Native Modulesを作成していきます。

CustomNativeModuleファイルの作成

android/app/src/main/java/com/your-app-name/のフォルダにファイルを作成します。

本記事では、CustomNativeModuleJavaというファイル名にしましたが、任意の名前にしてください。

よく使いそうなメソッド + 具体的なメソッドを実装しています。

  • シンプルなメソッド
  • callbackを返すメソッド
  • 引数を取るメソッド
  • Promiseを扱うメソッド
  • OSのバージョンを返すメソッド

モグモグさん

重要なポイントはコメントに記載しているので、確認してください。

メソッドは、@ReactMethodをつけることで、JavaScript側から呼ぶことができます。

// ご自身のパッケージ名
package com.nativemoduleexample;
import android.os.Build;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

// ReactContextBaseJavaModuleを継承している点がポイント
public class CustomNativeModuleJava extends ReactContextBaseJavaModule {
    public CustomNativeModuleJava(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    // getNameは必須で、JavaScriptから呼ぶ際のModule名になる
    @Override
    public String getName() {
        return "CustomNativeModuleJava";
    }

    // 出力するだけのメソッド
    @ReactMethod
    public void funcSimple() {
        System.out.print("funcSimple");
    }

    // callbackメソッド
    @ReactMethod
    public void funcCallback(Callback callback) {
        callback.invoke("funcCallback");
    }

    // 引数を取るcallbackメソッド
    @ReactMethod
    public void funcCallbackWithParams(String param, Callback callback) {
        callback.invoke("funcCallbackWithParams", param);
    }

    // Promise resolveパターンのメソッド
    @ReactMethod
    public void funcResolvePromise(Promise promise) {
        promise.resolve("funcResolvePromise");
    }

    // Promise rejectパターンのメソッド
    @ReactMethod
    public void funcRejectPromise(Promise promise) {
        promise.reject("error", "funcRejectPromise");
    }

    // 実用例: OSのバージョンを返すメソッド
    @ReactMethod
    public void getOSInfo(Callback callback) {
        callback.invoke("android", Build.VERSION.RELEASE);
    }
}

ReactPackageにModuleを追加

続いてReactPackageにModuleを追加します。

android/app/src/main/java/com/your-app-name/のフォルダにファイルを作成します。

// ご自身のパッケージ名
package com.nativemoduleexample;

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;

// implements ReactPackageがポイント
public class CustomNativeModuleJavaPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        // 実装したmoduleを追加
        modules.add(new CustomNativeModuleJava(reactContext));
        return modules;
    }
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

MainApplicationにModuleを追加

続いて、MainApplicationにModuleを追加していきます。

変更点は、packages.add(new CustomNativeModuleJavaPackage());の箇所です。

作成したmoduleを追加してください。

モグモグさん

変更点はここのみなので、全体のファイルは省略しています。

@Override
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 CustomNativeModuleJavaPackage());
  return packages;
}

JavaScript側から使う

カスタムのNative Modulesを作成したので、JavaScript側から使う方法を解説していきます。

App.jsでimport

Moduleの名前は、ご自身で定義したものを使ってください。

import {NativeModules} from 'react-native';

const App = () => {
  const {CustomNativeModuleJava} = NativeModules;
}

ch各メソッドを呼ぶ

呼ぶ場所は、任意ですが本記事では、useEffect内でそれぞれのメソッドを呼んでみました。

const App = () => {
  useEffect(() => {
    CustomNativeModuleJava.getOSInfo((name, os) => {
      console.log(name, os);
    });

    CustomNativeModuleJava.funcSimple();

    CustomNativeModuleJava.funcCallback(result => {
      console.log(result);
    });

    CustomNativeModuleJava.funcCallbackWithParams('test', (result, param) => {
      console.log(result, param);
    });

    (async () => {
      const result = await CustomNativeModuleJava.funcResolvePromise();
      console.log(result);
    })();

    (async () => {
      try {
        await CustomNativeModuleJava.funcRejectPromise();
      } catch (err) {
        console.error(err);
      }
    })();
  }, []);
}

実行結果

実行結果

実装したModuleのメソッドがそれぞれ呼ばれていることが分かりますね。

まとめ

モグモグさん

お疲れ様でした!

Android向けにJavaを用いて、NativeModulesを実装する方法を解説しました。

React Nativeを実装する上で非常に有用なので、ぜひ実際に使ってみてください!