Native Module 생성
Native Module 생성
네이티브 모듈이란
React Native에서 지원하지 않는 Android,IOS 만의 전용 기능을 가진 코드
🚗 Android 네이티브 모듈만들기 ( Java )
Android Studio > ReactNative 프로젝트 / android 폴더 열기
1. 모듈 클래스 만들기
2. ReactNative에 연결할 패키지 만들기
3. 만든 패키지 등록하기
Copy
// app/java/com.nativemoduleworkshop/pakagename.java
package com.pakagename.newarchitecture;
import android.app.Application;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.JSIModulePackage;
import com.facebook.react.bridge.JSIModuleProvider;
import com.facebook.react.bridge.JSIModuleSpec;
import com.facebook.react.bridge.JSIModuleType;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.fabric.CoreComponentsRegistry;
import com.facebook.react.fabric.EmptyReactNativeConfig;
import com.facebook.react.fabric.FabricJSIModuleProvider;
import com.facebook.react.fabric.ReactNativeConfig;
import com.facebook.react.uimanager.ViewManagerRegistry;
//ReactNative Java 모듈 상속
import com.pakagename.BuildConfig;
import com.pakagename.newarchitecture.components.MainComponentsRegistry;
import com.pakagename.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
import java.util.ArrayList;
import java.util.List;
// ReactNative에 등록할 패키지를 만들기
/**
* A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
* TurboModule delegates and the Fabric Renderer.
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
public class MainApplicationReactNativeHost extends ReactNativeHost {
public MainApplicationReactNativeHost(Application application) {
super(application);
}
@Override
public boolean getUseDeveloperSupport() {
/*
패키지를 받아오는 부분
*/
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
// packages.add(new TurboReactPackage() { ... });
// If you have custom Fabric Components, their ViewManagers should also be loaded here
// inside a ReactPackage.
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@NonNull
@Override
protected ReactPackageTurboModuleManagerDelegate.Builder
getReactPackageTurboModuleManagerDelegateBuilder() {
// Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
// for the new architecture and to use TurboModules correctly.
return new MainApplicationTurboModuleManagerDelegate.Builder();
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new JSIModulePackage() {
@Override
public List<JSIModuleSpec> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
final List<JSIModuleSpec> specs = new ArrayList<>();
// @ReactMethod 를 붙여주면,
// 이후 js 코드에서 호출 할 수 있다.
// Here we provide a new JSIModuleSpec that will be responsible of providing the
// custom Fabric Components.
specs.add(
new JSIModuleSpec() {
@Override
public JSIModuleType getJSIModuleType() {
return JSIModuleType.UIManager;
}
@Override
public JSIModuleProvider<UIManager> getJSIModuleProvider() {
final ComponentFactory componentFactory = new ComponentFactory();
CoreComponentsRegistry.register(componentFactory);
// Here we register a Components Registry.
// The one that is generated with the template contains no components
// and just provides you the one from React Native core.
MainComponentsRegistry.register(componentFactory);
final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
ViewManagerRegistry viewManagerRegistry =
new ViewManagerRegistry(
reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
return new FabricJSIModuleProvider(
reactApplicationContext,
componentFactory,
ReactNativeConfig.DEFAULT_CONFIG,
viewManagerRegistry);
}
});
return specs;
}
};
}
}
연결한 패키지 사용하기
Copy
// 프로젝트/App.js
import { NativeModules } from 'react-native'
const App = () => {
const { ToastModule } = NativeModules;
ToastModule.show('Hello Module!', ToastModule.SHORT);
return ...
}
🚗 코틀린으로 만들기
React Native 프로젝트 코틀린으로 변경하기
프로젝트 / android / build.gradle 파일 수정
Copy
...
buildscript {
ext {
buildToolsVersion = "31.0.0"
minSdkVersion = 21
compileSdkVersion = 31
targetSdkVersion = 31
kotlinVersion = "1.5.0" // 코틀린 추가
...
}
...
dependencies {
classpath("com.android.tools.build:gradle:7.1.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:5.0.1")
// 코틀린 추가
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
...
}
...
}
프로젝트 / android / app / build.gradle 파일 수정
Copy
...
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
...
}
// 맨 마지막 줄 아래에 작성
apply plugin: 'kotlin-android'
모듈 만들기
Copy
// 프로젝트/app/java/com.nativemoduleworkshop/BrightnessModule.kt
package com.nativemoduleworkshop
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
// ReactContext 모듈 상속 받기 ( 코틀린 방식 )
class BrightnessModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
// 모듈 이름 지정
override fun getName(): String {
return "BrightnessModule"
}
// 상수 내보내기
override fun getConstants(): MutableMap<String, Any>? {
val constants = HashMap<String, Any>()
constants.put("SAMPLE_VALUE", "Hello World")
return constants;
}
// 모듈에서 사용할 메서드 정의
@ReactMethod
fun getBrightness(){
}
@ReactMethod
fun setBrightness(brightness: Float){
}
}
패키지 만들기
Copy
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
import java.util.Collections
import kotlin.collections.ArrayList
class BrightnessPackage : ReactPackage {
// 모듈 등록
override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
val modules = ArrayList<NativeModule>()
modules.add(BrightnessModule(reactContext))
return modules;
}
// 네이티브 UI 컴포넌트 등록
override fun createViewManagers(reactContext: ReactApplicationContext): MutableList<ViewManager<*, ReactShadowNode<*>>> {
return Collections.emptyList();
}
}
패키지 등록하기
Java와 동일한 방법으로 패키지 등록하기
Copy
// app/java/com.nativemoduleworkshop/MainApplication.java
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() { ... }
/*
패키지를 받아오는 부분
*/
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// toast 패키지 추가
packages.add(new ToastPackage());
// Brightness 패키지 추가
packages.add(new BrightnessPackage());
return packages;
}
@Override
protected String getJSMainModuleName() { ... }
};
...
}
🚗 IOS 네이티브 모듈만들기 ( Objective.c )
XCode > ReactNative 프로젝트 / ios / 프로젝트.xcworkspace 열기
Header File 생성
프로젝트 / 프로젝트 폴더 우클릭 > New FIle > Header File
Header File 작성, 저장
Copy
// RCTBridgeModule 헤더파일 불러오기
#import <React/RCTBridgeModule.h>
// js 호출 가능한 메서드 만들기 위한 헤더파일
#import <UIKit/UIKit.h>
// RCTBridgeModule 객체를, RCTAlertModule라는 이름으로 사용하겠다.
@interface RCTAlertModule : NSObject <RCTBridgeModule>
@end
Objective.c File 생성
프로젝트 / 프로젝트 폴더 우클릭 > New FIle > Objective.c File
Objective.c File 작성, 저장
Copy
,/// RCTAlertModule.m
// 헤더파일 가져오기
#import "RCTAlertModule.h"
// 헤더파일에서 작성한 RCTAlertModule 상속 받기
@implementation RCTAlertModule
/* 네이티브 모듈 내보내는 메서드
인자로 모듈의 이름을 지정한다.
인자를 지정하지 않으면, 클래스 이름에서 RCT를 제외한 부분을 이름으로 사용한다 (AlertModule)
인자를 문자열 ""로 지정하지 말것!
*/
RCT_EXPORT_MODULE();
// js에서 호출 가능한 메서드 만들기
RCT_EXPORT_METHOD(alert:(NSString *)message)
{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert"message:@"This is an alert." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@:"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
// UI관련 작업을 main스레드에서 실행
dispatch_async(dispatch_get_main_queue(), ^{
[rootViewController presentViewController:alert animated:YES completion:nil]
})
}
// 상수 내보내기
- (NSDictionary *)constantsToExport
{
return @{
@"STRING_VALUE": @"Hello World",
@"NUMBER_VALUE": @(15)
};
}
// 모듈이 js 코드를 실행하기 전에, main스레드에서 상수 초기화 하기
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
@end
모듈 사용하기
Copy
// 프로젝트/App.js
import { NativeModules } from 'react-native'
const App = () => {
const { AlertModule } = NativeModules;
AlertModule.alert('Hello Module!');
console.log(AlertModule.NUMBER_VALUE);
return ...
}
🚗 Swift로 만들기
XCode > ReactNative 프로젝트 / ios / 프로젝트.xcworkspace 열기
Swift File 생성
프로젝트 / 프로젝트 폴더 우클릭 > New FIle > Swift File
Create Bridging Header 생성 ( 버튼 클릭 )
Copy
// NativeModuleWorkshop-Bridging-Header.h
#import "React/RCTBridgeModule.h"
Swift File 작성, 저장
Copy
dfsdf