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

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

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

モグモグさん

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

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

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

モグモグさん

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

【Android・Java】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で開発環境を作って始める

Kotlinを動かす

まずは、React NativeでKotlinを動かす方法を解説します。

build.gradlekotlin-gradle-pluginを追加

モグモグさん

app/の外のbuild.gradleに追加します。

変更点のある箇所だけ記載しています。

buildscript {
    ext {
        kotlin_version = '1.5.20'
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

app/内のbuild.gradleを更新

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

動作確認

モグモグさん

Kotlinが動作するようになったので、動作確認をして問題なくビルドができるか確認しましょう。

Native Modulesの作成

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

CustomNativeModuleファイルの作成

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

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

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

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

モグモグさん

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

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

// ご自身のパッケージ名
package com.nativemoduleexample
import android.os.Build
import com.facebook.react.bridge.*

// ReactContextBaseJavaModuleを継承している点がポイント
class CustomNativeModuleKotlin(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

    // getNameは必須で、JavaScriptから呼ぶ際のModule名になる
    override fun getName(): String {
        return "CustomNativeModuleKotlin"
    }

    // 出力するだけのメソッド
    @ReactMethod
    fun funcSimple() {
        print("funcSimple")
    }
    
    // callbackメソッド
    @ReactMethod
    fun funcCallback(callback: Callback) {
        callback.invoke("funcCallback")
    }

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

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

    // Promise rejectパターンのメソッド
    @ReactMethod
    fun funcRejectPromise(promise: Promise) {
        promise.reject("error", "funcRejectPromise")
    }
    
    // 実用例: OSのバージョンを返すメソッド
    @ReactMethod
    fun 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

class Main : ReactPackage {

    override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
        return emptyList()
    }

    override fun createNativeModules(
            reactContext: ReactApplicationContext): List<NativeModule> {
        val modules = ArrayList<NativeModule>()

        // moduleを追加
        modules.add(CustomNativeModuleKotlin(reactContext))

        return modules
    }

}

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 Main());
  return packages;
}

JavaScript側から使う

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

App.jsでimport

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

import {NativeModules} from 'react-native';

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

各メソッドを呼ぶ

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

const App = () => {
  useEffect(() => {
        CustomNativeModuleKotlin.getOSInfo((name, os) => {
      console.log(name, os);
    });
    CustomNativeModuleKotlin.funcSimple();
    CustomNativeModuleKotlin.funcCallback(result => {
      console.log(result);
    });
    CustomNativeModuleKotlin.funcCallbackWithParams('test', (result, param) => {
      console.log(result, param);
    });

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

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

実行結果

実行結果

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

まとめ

モグモグさん

お疲れ様でした!

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

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