我的 SDK 版本33,安装的模拟器上并没有闪光灯这个功能(灰色),所以只能连接真机才能看得到效果,在模拟器上会报以下错:
setTorchMode:2246: Camera "0" does not have a flash unit
但是在真机上就是正常的~
目录
一、创建手电筒 FlashLight 模块
将创建的 FlashLight.java 放置在 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;
}
/**
* 继承ReactContextBaseJavaModule后重写的方法,返回一个模块名称,rn通过NativeModules可以调用此模块
*/
@Override
public String getName() {
return "FlashLight";
}
/**
* @param state 控制手电筒开关,true:打开,false:关闭
* @param successCallback 打开成功的回调
* @param failCallback 打开失败的回调
*/
@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;
}
}
}
上面的 FlashLight 类继承自 ReactContextBaseJavaModule ,需要重写 getName 方法,返回一个模块供 rn 调用,getName 返回的就是调用的名称。
然后写一个方法 switchState 来控制手电筒开关,注意要加上 @ReactMethod 注解才能被调用,具体代码还包括不同 Android 版本的适配,都是 Android 原生的代码
二、注册手电筒 FlashLightPackage 模块
在 app/src/main/java/com/your-project-name 中新建 FlashLightPackage.java 包
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<>();
// 注册FlashLight模块
modules.add(new FlashLight(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
实现ReactPackage的两个方法,在createNativeModules里添加注册FlashLight模块
三、添加 FlashLightPackage 包
在同级目录下的 MainApplication.java 中的getPackages方法里添加刚才的FlashLightPackage包:
@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()); // <-- 添加这一行,类名替换成你的Package类的名字 name.
return packages;
}
四、添加权限
在AndroidManifest.xml配置文件里添加照相机和闪光灯的权限:
<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" />
五、将原生模块封装成 JavaScript 模块
// FlashLight.js
import { NativeModules } from 'react-native';
// 下一句中的FlashLight即对应上文
// public String getName()中返回的字符串
export default NativeModules.FlashLight;
六、调用方法
从NativeModules取出FlashLight模块,然后调用FlashLight的switchState来打开和关闭手电筒
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>打开手电筒</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
closeFlashLight();
}}>
<Text>关闭手电筒</Text>
</TouchableOpacity>
</View>
);
}