diff --git a/android/src/main/java/com/cubicphuse/RCTTorch/RCTTorchModule.java b/android/src/main/java/com/cubicphuse/RCTTorch/RCTTorchModule.java index f212f70..0d37fef 100644 --- a/android/src/main/java/com/cubicphuse/RCTTorch/RCTTorchModule.java +++ b/android/src/main/java/com/cubicphuse/RCTTorch/RCTTorchModule.java @@ -2,42 +2,74 @@ * Created by Ludo van den Boom on 06/04/2017. */ -package com.cubicphuse.RCTTorch; + package com.cubicphuse.RCTTorch; -import android.content.Context; -import android.hardware.Camera; -import android.hardware.camera2.CameraAccessException; -import android.hardware.camera2.CameraManager; -import android.os.Build; + import android.content.Context; + import android.hardware.Camera; + import android.hardware.camera2.CameraAccessException; + import android.hardware.camera2.CameraManager; + import android.os.Build; + import android.os.Handler; + import android.os.Looper; -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; + 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 RCTTorchModule extends ReactContextBaseJavaModule { private final ReactApplicationContext myReactContext; private Boolean isTorchOn = false; private Camera camera; + private CameraManager cameraManager; public RCTTorchModule(ReactApplicationContext reactContext) { super(reactContext); // Need access to reactContext to check for camera this.myReactContext = reactContext; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + cameraManager = + (CameraManager) this.myReactContext.getSystemService(Context.CAMERA_SERVICE); + } } + CameraManager.TorchCallback torchCallback = new CameraManager.TorchCallback() { + @Override + public void onTorchModeUnavailable(String cameraId) { + super.onTorchModeUnavailable(cameraId); + } + + @Override + public void onTorchModeChanged(String cameraId, boolean enabled) { + super.onTorchModeChanged(cameraId, enabled); + isTorchOn = enabled; + } + }; + @Override public String getName() { return "RCTTorch"; } @ReactMethod - public void switchState(Boolean newState, Callback successCallback, Callback failureCallback) { + public void getTorchStatus(Callback successCallback, Callback failureCallback) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - CameraManager cameraManager = - (CameraManager) this.myReactContext.getSystemService(Context.CAMERA_SERVICE); + cameraManager.registerTorchCallback(torchCallback, null); + try { + successCallback.invoke(isTorchOn); + } catch (Exception e) { + String errorMessage = e.getMessage(); + failureCallback.invoke("Error: " + errorMessage); + } + } + } + @ReactMethod + public void switchState(Boolean newState, Callback successCallback, Callback failureCallback) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { try { String cameraId = cameraManager.getCameraIdList()[0]; cameraManager.setTorchMode(cameraId, newState); diff --git a/index.android.js b/index.android.js index d98e8d8..d1063d6 100644 --- a/index.android.js +++ b/index.android.js @@ -58,6 +58,20 @@ async function requestCameraPermission( } } +async function getStatus(): Promise { + let done; + let failure; + + const result = new Promise((resolve, reject) => { + done = resolve; + failure = reject; + }); + + Torch.getTorchStatus(done, failure); + + return result; +} + async function switchState(newState: boolean): Promise { let done; let failure; @@ -73,8 +87,9 @@ async function switchState(newState: boolean): Promise { const TorchWithPermissionCheck = { ...Torch, - switchState, - requestCameraPermission + getStatus, + requestCameraPermission, + switchState }; export default TorchWithPermissionCheck; diff --git a/ios/RCTTorch.m b/ios/RCTTorch.m index 3cb0362..fbe0aad 100644 --- a/ios/RCTTorch.m +++ b/ios/RCTTorch.m @@ -13,22 +13,39 @@ @implementation RCTTorch RCT_EXPORT_MODULE() -RCT_EXPORT_METHOD(switchState:(BOOL *)newState) +RCT_EXPORT_METHOD(switchState:(nonnull NSNumber*)newState) { if ([AVCaptureDevice class]) { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if ([device hasTorch]){ [device lockForConfiguration:nil]; - - if (newState) { + + if ([newState boolValue]) { [device setTorchMode:AVCaptureTorchModeOn]; } else { [device setTorchMode:AVCaptureTorchModeOff]; } - + [device unlockForConfiguration]; } } } +RCT_EXPORT_METHOD(getStatus:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + if ([AVCaptureDevice class]) { + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if ([device hasTorch]){ + BOOL isOn = device.torchMode == AVCaptureTorchModeOn; + resolve([NSNumber numberWithBool:isOn]); + } else { + NSError *error = [[NSError alloc] initWithDomain:@"torch" code:0 userInfo:nil]; + reject(@"no_torch_available", @"This device has no torch", error); + } + } else { + NSError *error = [[NSError alloc] initWithDomain:@"torch" code:0 userInfo:nil]; + reject(@"no_torch_available", @"This device has no torch", error); + } +} + @end