I want to use native functions with React Native! Isn't there a time? However, there is no third party I'm looking for from GitHub. It's full of bugs and not maintained. And so on, the native side must also write. A situation like this occurs.
I would like to share a method to bridge native functions to React (js) side, which is useful in such a case.
TL;DR
--Https://github.com/react-native-community/react-native-camera is the subject --Create a module class that uses Android functions directly --Create a package class that implements the ReactPackage interface to handle the created module on the React side.
When using Android's Native function, there are functions without View such as voice and background processing, and functions with View such as camera preview.
Since the method of passing the value to React differs depending on whether there is a View or not, we will consider it separately here.
RNCameraPackage.java
package ...
import ...
public class RNCameraPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) {
return Arrays.<NativeModule>asList(
new RCTCameraModule(reactApplicationContext),
new CameraModule(reactApplicationContext),
new FaceDetectorModule(reactApplicationContext)
);
}
// Deprecated in RN 0.47
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
return Arrays.<ViewManager>asList(
new RCTCameraViewManager(),
new CameraViewManager()
);
}
}
In the java file on the android / app / src side, create a class that inherits the ReactContextBaseJavaModule
class.
Write the Module name
Define constants to be used on React side (without it)
Define the method to be used on React side. At this time, @ReactMethod annotation is added.
CameraModule.java
//①
public class CameraModule extends ReactContextBaseJavaModule {
private static final String TAG = "CameraModule";
...
public CameraModule(ReactApplicationContext reactContext) {
super(reactContext);
mScopedContext = new ScopedContext(reactContext);
}
...
//②
@Override
public String getName() {
return "RNCameraModule";
}
//③
@Override
public Map<String, Object> getConstants() {
return Collections.unmodifiableMap(new HashMap<String, Object>() {
{
put("Type", getTypeConstants());
put("FlashMode", getFlashModeConstants());
...
}
});
}
...
//④
@ReactMethod
public void takePicture(final ReadableMap options, final int viewTag, final Promise promise) {
final ReactApplicationContext context = getReactApplicationContext();
final File cacheDirectory = mScopedContext.getCacheDirectory();
UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
RNCameraView cameraView = (RNCameraView) nativeViewHierarchyManager.resolveView(viewTag);
try {
if (cameraView.isCameraOpened()) {
cameraView.takePicture(options, promise, cacheDirectory);
} else {
promise.reject("E_CAMERA_UNAVAILABLE", "Camera is not running");
}
} catch (Exception e) {
promise.reject("E_CAMERA_BAD_VIEWTAG", "takePictureAsync: Expected a Camera component");
}
}
});
}
...
}
Object => ReadableMap
Array => ReadableArray
Replace the type with and use the argument.
Also, use
com.facebook.react.uimanager.ViewGroupManager
ViewGroupManager
createViewInstanceOverride
to describe the UI Component you want to use and create a method that returns that componentCameraViewManager.java
package com.example;
//①
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
//②
public class CameraViewManager extends ViewGroupManager<RNCameraView> {
private static final String REACT_CLASS = "RNCamera";
@Override
public void onDropViewInstance(RNCameraView view) {
view.stop();
super.onDropViewInstance(view);
}
//③
// Component name that will be called from JavaScript
@Override
public String getName() {
return REACT_CLASS;
}
//④
// Return the view component instantiated with Activity context
@Override
public TextView createViewInstance(ThemedReactContext reactContext) {
return new RNCameraView(themedReactContext);
}
}
RNCamera.js
so that it can be used as a separate file.OriginalCamera.js
import { NativeModules } from `react-native`;
export default NativeModules.RNCameraModule;
Recommended Posts