fix snapshot orientation when device orientation is locked (#232)
* use device orientation on android only with auto orientation * guard against missing playSoundOnCapture and quality props in options * add video orientation support * use device orientation on ios only with auto orientation
This commit is contained in:
parent
f9137824a0
commit
0c3dba1ff6
|
@ -132,6 +132,10 @@ public class RCTCamera {
|
|||
return result;
|
||||
}
|
||||
|
||||
public int getOrientation() {
|
||||
return _orientation;
|
||||
}
|
||||
|
||||
public void setOrientation(int orientation) {
|
||||
if (_orientation == orientation) {
|
||||
return;
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.os.Environment;
|
|||
import android.provider.MediaStore;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import com.facebook.react.bridge.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -36,11 +37,11 @@ public class RCTCameraModule extends ReactContextBaseJavaModule {
|
|||
public static final int RCT_CAMERA_CAPTURE_TARGET_DISK = 1;
|
||||
public static final int RCT_CAMERA_CAPTURE_TARGET_CAMERA_ROLL = 2;
|
||||
public static final int RCT_CAMERA_CAPTURE_TARGET_TEMP = 3;
|
||||
public static final int RCT_CAMERA_ORIENTATION_AUTO = 0;
|
||||
public static final int RCT_CAMERA_ORIENTATION_LANDSCAPE_LEFT = 1;
|
||||
public static final int RCT_CAMERA_ORIENTATION_LANDSCAPE_RIGHT = 2;
|
||||
public static final int RCT_CAMERA_ORIENTATION_PORTRAIT = 3;
|
||||
public static final int RCT_CAMERA_ORIENTATION_PORTRAIT_UPSIDE_DOWN = 4;
|
||||
public static final int RCT_CAMERA_ORIENTATION_AUTO = Integer.MAX_VALUE;
|
||||
public static final int RCT_CAMERA_ORIENTATION_PORTRAIT = Surface.ROTATION_0;
|
||||
public static final int RCT_CAMERA_ORIENTATION_PORTRAIT_UPSIDE_DOWN = Surface.ROTATION_180;
|
||||
public static final int RCT_CAMERA_ORIENTATION_LANDSCAPE_LEFT = Surface.ROTATION_90;
|
||||
public static final int RCT_CAMERA_ORIENTATION_LANDSCAPE_RIGHT = Surface.ROTATION_270;
|
||||
public static final int RCT_CAMERA_TYPE_FRONT = 1;
|
||||
public static final int RCT_CAMERA_TYPE_BACK = 2;
|
||||
public static final int RCT_CAMERA_FLASH_MODE_OFF = 0;
|
||||
|
@ -176,16 +177,21 @@ public class RCTCameraModule extends ReactContextBaseJavaModule {
|
|||
|
||||
@ReactMethod
|
||||
public void capture(final ReadableMap options, final Promise promise) {
|
||||
_sensorOrientationChecker.onResume();
|
||||
_sensorOrientationChecker.registerOrientationListener(new RCTSensorOrientationListener() {
|
||||
@Override
|
||||
public void orientationEvent() {
|
||||
int deviceOrientation = _sensorOrientationChecker.getOrientation();
|
||||
_sensorOrientationChecker.unregisterOrientationListener();
|
||||
_sensorOrientationChecker.onPause();
|
||||
captureWithOrientation(options, promise, deviceOrientation);
|
||||
}
|
||||
});
|
||||
int orientation = options.hasKey("orientation") ? options.getInt("orientation") : RCTCamera.getInstance().getOrientation();
|
||||
if (orientation == RCT_CAMERA_ORIENTATION_AUTO) {
|
||||
_sensorOrientationChecker.onResume();
|
||||
_sensorOrientationChecker.registerOrientationListener(new RCTSensorOrientationListener() {
|
||||
@Override
|
||||
public void orientationEvent() {
|
||||
int deviceOrientation = _sensorOrientationChecker.getOrientation();
|
||||
_sensorOrientationChecker.unregisterOrientationListener();
|
||||
_sensorOrientationChecker.onPause();
|
||||
captureWithOrientation(options, promise, deviceOrientation);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
captureWithOrientation(options, promise, orientation);
|
||||
}
|
||||
}
|
||||
|
||||
public void captureWithOrientation(final ReadableMap options, final Promise promise, int deviceOrientation) {
|
||||
|
@ -195,8 +201,16 @@ public class RCTCameraModule extends ReactContextBaseJavaModule {
|
|||
return;
|
||||
}
|
||||
|
||||
if (options.hasKey("playSoundOnCapture") && options.getBoolean("playSoundOnCapture")) {
|
||||
MediaActionSound sound = new MediaActionSound();
|
||||
sound.play(MediaActionSound.SHUTTER_CLICK);
|
||||
}
|
||||
|
||||
if (options.hasKey("quality")) {
|
||||
RCTCamera.getInstance().setCaptureQuality(options.getInt("type"), options.getString("quality"));
|
||||
}
|
||||
|
||||
RCTCamera.getInstance().adjustCameraRotationToDeviceOrientation(options.getInt("type"), deviceOrientation);
|
||||
RCTCamera.getInstance().setCaptureQuality(options.getInt("type"), options.getString("quality"));
|
||||
camera.takePicture(null, null, new Camera.PictureCallback() {
|
||||
@Override
|
||||
public void onPictureTaken(byte[] data, Camera camera) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.hardware.Sensor;
|
|||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
|
||||
|
@ -51,13 +52,13 @@ public class RCTSensorOrientationChecker {
|
|||
float y = event.values[1];
|
||||
|
||||
if (x<5 && x>-5 && y > 5)
|
||||
mOrientation = 0;
|
||||
mOrientation = Surface.ROTATION_0; // portrait
|
||||
else if (x<-5 && y<5 && y>-5)
|
||||
mOrientation = 3;
|
||||
mOrientation = Surface.ROTATION_270; // right
|
||||
else if (x<5 && x>-5 && y<-5)
|
||||
mOrientation = 2;
|
||||
mOrientation = Surface.ROTATION_180; // upside down
|
||||
else if (x>5 && y<5 && y>-5)
|
||||
mOrientation = 1;
|
||||
mOrientation = Surface.ROTATION_90; // left
|
||||
|
||||
if (mListener != null) {
|
||||
mListener.orientationEvent();
|
||||
|
|
|
@ -29,13 +29,15 @@
|
|||
|
||||
- (void)setOrientation:(NSInteger)orientation
|
||||
{
|
||||
[self.manager changeOrientation:orientation];
|
||||
|
||||
if (orientation == RCTCameraOrientationAuto) {
|
||||
[self.manager changeOrientation:[UIApplication sharedApplication].statusBarOrientation];
|
||||
[self changePreviewOrientation:[UIApplication sharedApplication].statusBarOrientation];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
|
||||
}
|
||||
else {
|
||||
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
|
||||
[self.manager changeOrientation:orientation];
|
||||
[self changePreviewOrientation:orientation];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,7 +111,7 @@
|
|||
|
||||
- (void)orientationChanged:(NSNotification *)notification{
|
||||
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
[self.manager changeOrientation:orientation];
|
||||
[self changePreviewOrientation:orientation];
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,5 +179,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)changePreviewOrientation:(NSInteger)orientation
|
||||
{
|
||||
if (self.manager.previewLayer.connection.isVideoOrientationSupported) {
|
||||
self.manager.previewLayer.connection.videoOrientation = orientation;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -303,9 +303,6 @@ RCT_EXPORT_METHOD(checkAudioAuthorizationStatus:(RCTPromiseResolveBlock)resolve
|
|||
|
||||
RCT_EXPORT_METHOD(changeOrientation:(NSInteger)orientation) {
|
||||
[self setOrientation:orientation];
|
||||
if (self.previewLayer.connection.isVideoOrientationSupported) {
|
||||
self.previewLayer.connection.videoOrientation = orientation;
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(capture:(NSDictionary *)options
|
||||
|
@ -408,7 +405,6 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
|
|||
});
|
||||
}]];
|
||||
|
||||
[self.previewLayer.connection setVideoOrientation:self.orientation];
|
||||
[self.session startRunning];
|
||||
});
|
||||
}
|
||||
|
@ -484,8 +480,20 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
|
|||
});
|
||||
}
|
||||
|
||||
- (void)captureStill:(NSInteger)target options:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
||||
{
|
||||
AVCaptureVideoOrientation orientation = options[@"orientation"] != nil ? [options[@"orientation"] integerValue] : self.orientation;
|
||||
if (orientation == RCTCameraOrientationAuto) {
|
||||
[self.sensorOrientationChecker getDeviceOrientationWithBlock:^(UIInterfaceOrientation orientation) {
|
||||
[self captureStill:target options:options orientation:[self.sensorOrientationChecker convertToAVCaptureVideoOrientation: orientation] resolve:resolve reject:reject];
|
||||
}];
|
||||
} else {
|
||||
[self captureStill:target options:options orientation:orientation resolve:resolve reject:reject];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)captureStill:(NSInteger)target options:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
||||
- (void)captureStill:(NSInteger)target options:(NSDictionary *)options orientation:(AVCaptureVideoOrientation)orientation resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
||||
{
|
||||
dispatch_async(self.sessionQueue, ^{
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
CGSize size = CGSizeMake(720, 1280);
|
||||
|
@ -513,8 +521,7 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
|
|||
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
|
||||
[self saveImage:imageData target:target metadata:nil resolve:resolve reject:reject];
|
||||
#else
|
||||
[self.sensorOrientationChecker getDeviceOrientationWithBlock:^(UIInterfaceOrientation orientation) {
|
||||
[[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:[self.sensorOrientationChecker convertToAVCaptureVideoOrientation: orientation]];
|
||||
[[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:orientation];
|
||||
|
||||
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
|
||||
|
||||
|
@ -577,7 +584,6 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
|
|||
reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description));
|
||||
}
|
||||
}];
|
||||
}];
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
@ -659,8 +665,20 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
|
|||
return rotatedImage;
|
||||
}
|
||||
|
||||
-(void)captureVideo:(NSInteger)target options:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
|
||||
-(void)captureVideo:(NSInteger)target options:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
||||
{
|
||||
AVCaptureVideoOrientation orientation = options[@"orientation"] != nil ? [options[@"orientation"] integerValue] : self.orientation;
|
||||
if (orientation == RCTCameraOrientationAuto) {
|
||||
[self.sensorOrientationChecker getDeviceOrientationWithBlock:^(UIInterfaceOrientation orientation) {
|
||||
[self captureVideo:target options:options orientation:[self.sensorOrientationChecker convertToAVCaptureVideoOrientation: orientation] resolve:resolve reject:reject];
|
||||
}];
|
||||
} else {
|
||||
[self captureVideo:target options:options orientation:orientation resolve:resolve reject:reject];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)captureVideo:(NSInteger)target options:(NSDictionary *)options orientation:(AVCaptureVideoOrientation)orientation resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
||||
{
|
||||
if (self.movieFileOutput.recording) {
|
||||
reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Already recording"));
|
||||
return;
|
||||
|
@ -678,18 +696,18 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
|
|||
}
|
||||
|
||||
dispatch_async(self.sessionQueue, ^{
|
||||
[[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:self.previewLayer.connection.videoOrientation];
|
||||
[[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:orientation];
|
||||
|
||||
//Create temporary URL to record to
|
||||
NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
|
||||
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if ([fileManager fileExistsAtPath:outputPath]) {
|
||||
NSError *error;
|
||||
if ([fileManager removeItemAtPath:outputPath error:&error] == NO) {
|
||||
reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description));
|
||||
return;
|
||||
}
|
||||
NSError *error;
|
||||
if ([fileManager removeItemAtPath:outputPath error:&error] == NO) {
|
||||
reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Start recording
|
||||
|
|
Loading…
Reference in New Issue