react native Android Native module은 React Native module이 따로 없을 때, 사용하는 Native moudle
-바로 React Native application Android projects에 작성, 아니면 NPM package설치

이 과정은 JS에서 Android CalendarModule로 접근하기 위해서 CalendarModule을 만드는 과정임
Native module을 작성할 때에는 Android studio를 사용하는 것이 code syntax error도 잡을 수 있고 좋음

com.yourAppName 에 java class파일을 하나 만들고
package com.your-app-name; // replace com.your-app-name with your app’s 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 CalendarModule extends ReactContextBaseJavaModule {
CalendarModule(ReactApplicationContext context) {
super(context);
}
}
기본 모듈은 ReactContextBaseJavaModule로 확장하고, 필요한 기능을 구현
Module Name
모든 기본 모듈은 getName() 메서드를 구현해야 함
// add to CalendarModule.java
@Override
public String getName() {
return "CalendarModule";
}
const {CalendarModule} = ReactNative.NativeModules;
다음과 같이 JS에서 접근 가능
Javascript에서 호출되는 모든 기본 모듈 메서드에 @ReactMethod 주석이 추가
import android.util.Log;
@ReactMethod
public void createCalendarEvent(String name, String location) {
Log.d("CalendarModule", "Create event called with name: " + name
+ " and location: " + location);
}
동기 메서드로 표시하는 방법으로 isBlockingSynchronousMethod=true 전달
@ReactMethod(isBlockingSynchronousMethod = true)
Native Module이 작성되면 이 모듈을 React Native에 등록해야 된다.
com.yourAppName 에 javaPackage.java 파일을 하나 만들고 그 안에 코드를 작성해 준다.
package com.your-app-name; // replace your-app-name with your app’s 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 CalendarModule(reactContext));
return modules;
}
}
createNativeModules() 함수 내에서 calendarModule을 인스턴스화하고 등록할 NativeModules목록으로 반환, 여기에 추가할 네이티브 모듈을 작성
그리고, CalendarModule Package 를 MainApplication.java 에 등록
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// below MyAppPackage is added to the list of packages returned
packages.add(new MyAppPackage());
return packages;
}
JS에서 호출해서 사용하는 법!!
import React from 'react';
import {NativeModules, Button} from 'react-native';
const {CalendarModule} = NativeModules;
const NewModuleButton = () => {
const onPress = () => {
console.log('We will invoke the native module here!');
CalendarModule.createCalendarEvent('testName', 'testLocation');
};
return (
<Button
title="Click to invoke your native module!"
color="#841584"
onPress={onPress}
/>
);
};
export default NewModuleButton;
terminal에 입력
npx react-native run-android
JAVA로부터 상수 받기
@Override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put("DEFAULT_EVENT_NAME", "New Event");
return constants;
}
JS에서
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
console.log(DEFAULT_EVENT_NAME);
Callback도 사용 가능
import com.facebook.react.bridge.Callback;
@ReactMethod
public void createCalendarEvent(String name, String location, Callback callBack) {
Integer eventId = ...
callBack.invoke(eventId);
}
callback은 비동기메서드를 위해 java 에서 javascript로 데이터를 전달하는데 사용
const onPress = () => {
CalendarModule.createCalendarEvent(
'Party',
'My House',
(eventId) => {
console.log(`Created a new event with id ${eventId}`);
}
);
};
Promise도 사용 가능
import com.facebook.react.bridge.Promise;
@ReactMethod
public void createCalendarEvent(String name, String location, Promise promise) {
try {
Integer eventId = ...
promise.resolve(eventId);
} catch(Exception e) {
promise.reject("Create Event Error", e);
}
}
import com.facebook.react.bridge.Promise;
@ReactMethod
public void createCalendarEvent(String name, String location, Promise promise) {
try {
Integer eventId = ...
promise.resolve(eventId);
} catch(Exception e) {
promise.reject("Create Event Error", e);
}
}
Javscript로 이벤트 보내기
네이티브 모듈 호출 없이 JS로 이벤트 신호를 보낼 수 있음
->RCTDeviceEventEmitter을 사용
-Java-
...
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
...
private void sendEvent(ReactContext reactContext,
String eventName,
@Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
private int listenerCount = 0;
@ReactMethod
public void addListener(String eventName) {
if (listenerCount == 0) {
// Set up any upstream listeners or background tasks as necessary
}
listenerCount += 1;
}
@ReactMethod
public void removeListeners(Integer count) {
listenerCount -= count;
if (listenerCount == 0) {
// Remove upstream listeners, stop unnecessary background tasks
}
}
...
WritableMap params = Arguments.createMap();
params.putString("eventProperty", "someValue");
...
sendEvent(reactContext, "EventReminder", params);
-JS-
import {NativeEventEmitter, NativeModules} from 'react-native';
...
componentDidMount() {
...
const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);
this.eventListener = eventEmitter.addListener('EventReminder', event => {
console.log(event.eventProperty) // "someValue"
});
...
}
componentWillUnmount() {
this.eventListener.remove(); //Removes the listener
}