はじめまして。Argano の松田です。 本記事では、React Native で JavaScript からネイティブコードを呼び出す方法を紹介します。
Native Module
React Native でアプリを作成する際、次のような要望が出てくるかもしれません。
- Apple や Google Pay にアクセスするためのネイティブ API など、JavaScript ではデフォルトで利用できないネイティブプラットフォーム API にアクセスする必要がある
- 既存の Objective-C、Swift、Java、Kotlin、C++ ライブラリを JavaScript で再実装せずに再利用したい
- 画像処理などのために高性能なマルチスレッドコードを記述したい
そんな時に React Native の Native Module をいう機能を使用できます。
Native Module は、Objective-C、Swift、Java、Kotlin、C++ クラスのインスタンスを JavaScript オブジェクトとして公開し、それによって JavaScript の中から任意のネイティブコードを実行できるようにするものです。
今回は React Native アプリケーション内の JavaScript から ネイティブのメソッドを実行してみます。
最終的には、JavaScript から MyModule.log('Test');
を呼び出し、ネイティブにログ出力できるようにします。
Native Module の作成
環境構築は終わっている前提で進めます。Android の Native Module を作成するには Java か Kotlin を選ぶことができますが、今回は Java を使用します。
ます、android/app/src/main/java/com/your-app-name/
フォルダ内に、MyModule.java ファイルを作成します。
MyModule.java の内容
package com.your-app-name;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.Map;
import java.util.HashMap;
public class MyModule extends ReactContextBaseJavaModule {
MyModule(ReactApplicationContext context) {
super(context);
}
@Override
public String getName() {
return "MyModule";
}
}
Native Module は getName
メソッドを実装する必要があります。このメソッドは、Native Module の名前を表す文字列を返します。その名前を使用して JavaScript からアクセスできます。
// JavaScript からアクセス
const { MyModule } = ReactNative.NativeModules;
Native メソッドを JavaScript に書き出す
次に、Native Module にログを出力するメソッドを追加し、JavaScript から呼び出すことができるようにします。JavaScript から呼び出される Native Module のメソッドには、必ず @ReactMethod
のアノテーションを付けなければなりません。
MyModule に log
メソッドを実装します。
import android.util.Log;
@ReactMethod
public void log(String content) {
Log.d("MyModule", "Content: " + content);
}
Module の登録
Native Module を書いたら、それを React Native に登録する必要があります。そのためには、Native Module を ReactPackage に追加して、ReactPackage を React Native に登録します。 まず、Native Module を ReactPackage に追加します。android/app/src/main/java/com/your-app-name/ フォルダ内に MyAppPackage.java ファイルを新規に作成します。
MyAppPackage.java の内容
package com.your-app-name;
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;
public class MyAppPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new MyModule(reactContext));
return modules;
}
}
次に MainApplication.java を編集します。
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new MyAppPackage()); // 追加
return packages;
}
Native Module を JavaScript から呼び出す
JavaScript から Native Module にアクセスするためには、まず React Native から NativeModules をインポートする必要があります。
import { NativeModules } from 'react-native';
そして、NativeModules から MyModule のネイティブモジュールにアクセスできるようになります。
const { MyModule } = NativeModules;
あとは 実装したメソッドを呼び出すだけです。
const onPress = () => {
MyModule.log('log test');
};
最後に再ビルドを実行します。Native Module を修正した場合は JavaScript を修正した場合と違い、ホットリロードが効かないため注意が必要です。
npx react-native run-android
まとめ
Native Module の基本的な使い方を見てきました。アプリを作る中で使用する機会は少ないかもしれません。しかし、JavaScript での実装ができない場合は、ライブラリを探すか、Native Module を利用することになります。 JavaScript にイベントを送信したり、ライフサイクルメソッドを使用したりすることもできます。 React Native であれど、かなり柔軟にさまざまな要件を満たせそうです。