React Native has revolutionized mobile app development by enabling developers to build applications for both iOS and Android using a single codebase written in JavaScript. However, bridging the gap between native modules and JavaScript can sometimes be complex and error-prone. This is where Continuous Native Generation (CNG) comes into play, simplifying the integration and management of native code within React Native projects.
Continuous Native Generation is a concept and tooling approach aimed at automating the creation and integration of native modules in React Native applications. By continuously generating and updating native code, CNG streamlines the development workflow, reduces manual coding errors, and ensures that native modules are always in sync with the JavaScript code.
To demonstrate how Continuous Native Generation (CNG) can be used to open a native camera and gallery in a React Native application, let’s walk through a complete example. We’ll assume that CNG automates the creation of the necessary bridging code.
For this example, we’ll configure a native module to open the camera and gallery, generate the required native code, and then use it in a React Native app.
First, create a new React Native project:
npx react-native init CameraGalleryExample
cd CameraGalleryExample
Assuming we are using a hypothetical CNG tool named react-native-cng, install it via npm or yarn:
npm install react-native-cng --save-dev
Create a configuration file, cng.config.js, to define the native modules for opening the camera and gallery. Here’s an example configuration:
module.exports = {
nativeModules: [
{
name: 'MediaModule',
methods: [
{
name: 'openCamera',
returnType: 'void',
params: []
},
{
name: 'openGallery',
returnType: 'void',
params: []
}
]
}
]
};
This configuration specifies that we want to create a native module named MediaModule with two methods: openCamera and openGallery.
Run the CNG tool to generate the native modules:
npx react-native-cng generate
This command will generate the necessary native code for both Android and iOS based on the configuration provided.
Although CNG generates the boilerplate, you’ll need to implement the actual functionality in the native code.
For Android (Java/Kotlin):
package com.cameragalleryexample;
import android.app.Activity;
import android.content.Intent;
import android.provider.MediaStore;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class MediaModule extends ReactContextBaseJavaModule {
private static final int CAMERA_REQUEST = 1888;
private static final int GALLERY_REQUEST = 1889;
MediaModule(ReactApplicationContext context) {
super(context);
}
@Override
public String getName() {
return "MediaModule";
}
@ReactMethod
public void openCamera() {
Activity activity = getCurrentActivity();
if (activity != null) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
activity.startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
}
@ReactMethod
public void openGallery() {
Activity activity = getCurrentActivity();
if (activity != null) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
activity.startActivityForResult(galleryIntent, GALLERY_REQUEST);
}
}
}
For iOS (Objective-C/Swift):
#import
#import
@interface MediaModule : NSObject
@end
@implementation MediaModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(openCamera) {
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[rootViewController presentViewController:imagePicker animated:YES completion:nil];
});
}
RCT_EXPORT_METHOD(openGallery) {
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[rootViewController presentViewController:imagePicker animated:YES completion:nil];
});
}
@end
With the native modules generated and implemented, you can now use them in your React Native application:
import React from 'react';
import { Button, View } from 'react-native';
import { NativeModules } from 'react-native';
const { MediaModule } = NativeModules;
const App = () => {
return (
);
};
export default App;
Finally, build and run your React Native application to see the native camera and gallery modules in action:
npx react-native run-android
npx react-native run-ios
By automating the creation of the bridging code, Continuous Native Generation simplifies the integration of native functionality into React Native applications. This example demonstrates how CNG can be used to create and use native modules for opening the camera and gallery, reducing the need for manual coding and ensuring consistency across platforms.