1

首先新建一个rn项目

react-native init flashlight
之后用AndroidStudio打开项目的Android代码

新建手电筒模块

在app/java/com.flashlight下新建一个模块FlashLight.java:

package com.flashlight;
 
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调用

然后写一个方法switchState来控制手电筒开关,注意要加上@ReactMethod注解才能被调用,具体代码还包括不同Android版本的适配,都是Android原生的代码,不做过多解释

注册手电筒模块

之后在app/java/com.flashlight下新建一个包FlashLightPackage.java:

package com.flashlight;
 
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模块

最后,在MainApplication.java的getPackages方法里添加刚才的FlashLightPackage包:

package com.flashlight;
 
import android.app.Application;
 
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
 
import java.util.Arrays;
import java.util.List;
 
public class MainApplication extends Application implements ReactApplication {
 
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }
 
    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
              new FlashLightPackage()
      );
    }
 
    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };
 
  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }
 
  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

添加权限

在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" />

现在原生的接口已经写好,可以去rn调用这个接口来打开或者关闭手电筒了

React Native调用接口

修改App.js文件,添加两个按钮用于打开和关闭手电筒

import React, {Component} from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  NativeModules
} from 'react-native';
let FlashLight = NativeModules.FlashLight
 
export default class App extends Component<Props> {
 
  openFlashLight() {
    FlashLight.switchState(true, () => {
    }, (message) => {
      console.error(message)
    })
  }
 
  closeFlashLight() {
    FlashLight.switchState(false, () => {
    }, (message) => {
      console.error(message)
    })
  }
 
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={() => {
          this.openFlashLight()
        }}>
          <Text>打开手电筒</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => {
          this.closeFlashLight()
        }}>
          <Text>关闭手电筒</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
});

从NativeModules取出FlashLight模块,然后调用FlashLight的switchState来打开和关闭手电筒


一纶新岳
62 声望3 粉丝