RN calls Android flash

My SDK version 33 does not have the flash function (gray) on the installed simulator, so the effect can only be seen when connected to a real device. The following error will be reported on the simulator:

setTorchMode:2246: Camera “0” does not have a flash unit

But it’s normal on the real machine~

Table of Contents

1. Create the flashlight FlashLight module

2. Register the flashlight FlashLightPackage module

3. Add FlashLightPackage package

4. Add permissions

5. Encapsulate native modules into JavaScript modules

6. Calling method


1. Create flashlight FlashLight module

Place the created FlashLight.java in app/src/main/java/com/your-project-name

package com.invokingandroid;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class FlashLight extends ReactContextBaseJavaModule{
    private camera camera;
    private Boolean isLightOn = false;
    private final ReactApplicationContext myReactContext;
    public FlashLight(ReactApplicationContext reactContext) {
        super(reactContext);
        this.myReactContext = reactContext;
    }

    /**
     * A method rewritten after inheriting ReactContextBaseJavaModule and returns a module name. This module can be called through NativeModules
     */
    @Override
    public String getName() {
        return "FlashLight";
    }

    /**
     * @param state controls the flashlight switch, true: on, false: off
     * @param successCallback Open the success callback
     * @param failCallback Open failure callback
     */
    @ReactMethod
    public void switchState(Boolean state, Callback successCallback, Callback failCallback) {
        if (isM()) {
            CameraManager cameraManager = (CameraManager) this.myReactContext.getSystemService(Context.CAMERA_SERVICE);
            try {
                String camreaId = cameraManager.getCameraIdList()[0];
                cameraManager.setTorchMode(camreaId, state);
                successCallback.invoke(true);
            }catch (Exception e) {
                String errorMessage = e.getMessage();
                failCallback.invoke(errorMessage);
            }
        } else {
            Camera.Parameters params;
            if (!isLightOn) {
                camera = Camera.open();
                params = camera.getParameters();
                params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                camera.setParameters(params);
                camera.startPreview();
                isLightOn = true;
            } else {
                params = camera.getParameters();
                params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                camera.setParameters(params);
                camera.stopPreview();
                camera.release();
                isLightOn = false;
            }

        }
    }

    private boolean isM() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return true;
        } else {
            return false;
        }
    }
}

The FlashLight class above inherits from ReactContextBaseJavaModule and needs to override the getName method to return a module for rn to call. getName returns the name of the call.

Then write a method switchState to control the flashlight switch. Note that the @ReactMethod annotation must be added before it can be called. The specific code also includes adaptations for different Android versions, which are all Android native codes.

2. Register the flashlight FlashLightPackage module

Create a new FlashLightPackage.java package in app/src/main/java/com/your-project-name

package com.invokingandroid;

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 FlashLightPackage implements ReactPackage{

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        //Register FlashLight module
        modules.add(new FlashLight(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Two methods to implement ReactPackage, add registered FlashLight module in createNativeModules

3. Add FlashLightPackage package

Add the FlashLightPackage package just now in the getPackages method in MainApplication.java in the same directory:

 @Override
    protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for
      // example:
      // packages.add(new MyReactNativePackage());
      packages.add(new FlashLightPackage()); // <-- Add this line and replace the class name with the name of your Package class name.

      return packages;
    }

4. Add permissions

Add camera and flash permissions to the AndroidManifest.xml configuration file:

 <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.autofocus" />
    <uses-feature android:name="android.hardware.camera.flash" />

5. Encapsulate native modules into JavaScript modules

// FlashLight.js

import { NativeModules } from 'react-native';
// FlashLight in the next sentence corresponds to the above
// The string returned in public String getName()
export default NativeModules.FlashLight;

6. Calling method

Take out the FlashLight module from NativeModules and call FlashLight’s switchState to turn the flashlight on and off

function openFlashLight() {
  FlashLight.switchState(
    true,
    () => {},
    (message: any) => {
      console.error(message);
    },
  );
}

function closeFlashLight() {
  FlashLight.switchState(
    false,
    () => {},
    (message: any) => {
      console.error(message);
    },
  );
}


function App(): JSX.Element {
  return (
    <View style={styles.container}>
      <TouchableOpacity
        onPress={() => {
          openFlashLight();
        }}>
        <Text>Turn on the flashlight</Text>
      </TouchableOpacity>
      <TouchableOpacity
        onPress={() => {
          closeFlashLight();
        }}>
        <Text>Turn off the flashlight</Text>
      </TouchableOpacity>
    </View>
  );
}