Skip to content
This repository has been archived by the owner on Jun 16, 2023. It is now read-only.

[iOS] Make GoogleMobileVision framework optional #1341

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ pod 'react-native-camera', path: '../node_modules/react-native-camera'
1. `npm install react-native-camera --save`
2. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
3. Go to `node_modules` ➜ `react-native-camera` and add `RNCamera.xcodeproj`
4. In XCode, in the project navigator, select your project. Add `libRNCamera.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
5. Click `RNCamera.xcodeproj` in the project navigator and go the `Build Settings` tab. Make sure 'All' is toggled on (instead of 'Basic'). In the `Search Paths` section, look for `Header Search Paths` and make sure it contains both `$(SRCROOT)/../../react-native/React` and `$(SRCROOT)/../../../React` - mark both as `recursive`.
4. Expand the `RNCamera.xcodeproj` ➜ `Products` folder
5. In XCode, in the project navigator, select your project. Add `libRNCamera.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
6. Click `RNCamera.xcodeproj` in the project navigator and go the `Build Settings` tab. Make sure 'All' is toggled on (instead of 'Basic'). In the `Search Paths` section, look for `Header Search Paths` and make sure it contains both `$(SRCROOT)/../../react-native/React` and `$(SRCROOT)/../../../React` - mark both as `recursive`.

### Face Detection or Text Recognition Steps

Expand Down Expand Up @@ -150,7 +151,7 @@ Google Symbol Utilities: https://www.gstatic.com/cpdc/dbffca986f6337f8-GoogleSym

#### Android
1. `npm install react-native-camera --save`
2. Open up `android/app/src/main/java/[...]/MainApplication.java
2. Open up `android/app/src/main/java/[...]/MainApplication.java`
- Add `import org.reactnative.camera.RNCameraPackage;` to the imports at the top of the file
- Add `new RNCameraPackage()` to the list returned by the `getPackages()` method. Add a comma to the previous item if there's already something there.

Expand All @@ -164,8 +165,17 @@ Google Symbol Utilities: https://www.gstatic.com/cpdc/dbffca986f6337f8-GoogleSym
4. Insert the following lines inside the dependencies block in `android/app/build.gradle`:

```gradle
compile project(':react-native-camera')
compile (project(':react-native-camera')) {
exclude group: "com.google.android.gms"
compile 'com.android.support:exifinterface:25.+'
compile ('com.google.android.gms:play-services-vision:10.2.0') {
force = true
}
}
```

> You may need to use different versions, e.g. `27.+` instead of `25.+` and `11.8.0` instead of `10.2.0`.

5. Declare the permissions in your Android Manifest (required for `video recording` feature)

```java
Expand Down
5 changes: 5 additions & 0 deletions ios/FaceDetector/RNFaceDetectorManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <GoogleMobileVision/GoogleMobileVision.h>
#import <GoogleMVDataOutput/GoogleMVDataOutput.h>
#endif


@protocol RNFaceDetectorDelegate
- (void)onFacesDetected:(NSArray<NSDictionary *> *)faces;
@end

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
@interface RNFaceDetectorManager : NSObject

- (NSDictionary *)constantsToExport;
Expand All @@ -31,3 +35,4 @@
- (void)stopFaceDetection;

@end
#endif
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceDetectorManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Joao Guilherme Daros Fidelis on 21/01/18.
//

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <React/RCTConvert.h>
#import "RNCamera.h"
#import "RNFaceEncoder.h"
Expand Down Expand Up @@ -272,3 +273,4 @@ + (void)_initDefaultFaceDetectorOptions
}

@end
#endif
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceDetectorModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
//

#import <React/RCTBridgeModule.h>
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <GoogleMobileVision/GoogleMobileVision.h>
#endif

@interface RNFaceDetectorModule : NSObject <RCTBridgeModule>
@end
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceDetectorModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Joao Guilherme Daros Fidelis on 21/01/18.
//

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import "RNFaceDetectorModule.h"
#import "RNFaceEncoder.h"
#import "RNFileSystem.h"
Expand Down Expand Up @@ -193,3 +194,4 @@ + (int)exifOrientationFor:(UIImageOrientation)orientation
}

@end
#endif
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceDetectorUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Joao Guilherme Daros Fidelis on 21/01/18.
//

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <UIKit/UIKit.h>
#import <CoreMedia/CoreMedia.h>
#import <Foundation/Foundation.h>
Expand Down Expand Up @@ -33,3 +34,4 @@ typedef NS_ENUM(NSInteger, RNFaceDetectionClassifications) {
+ (CGAffineTransform)transformFromDeviceOutput:(GMVDataOutput *)dataOutput toInterfaceVideoOrientation:(AVCaptureVideoOrientation)interfaceVideoOrientation;

@end
#endif
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceDetectorUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Joao Guilherme Daros Fidelis on 21/01/18.
//

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import "RNCameraUtils.h"
#import "RNFaceDetectorUtils.h"
#import "RNFaceDetectorPointTransformCalculator.h"
Expand Down Expand Up @@ -75,3 +76,4 @@ + (CGAffineTransform)transformFromDeviceOutput:(GMVDataOutput *)dataOutput toInt
}

@end
#endif
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

#import <UIKit/UIKit.h>
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <GoogleMobileVision/GoogleMobileVision.h>

@interface RNFaceEncoder : NSObject
Expand All @@ -15,3 +16,4 @@
- (NSDictionary *)encode:(GMVFaceFeature *)face;

@end
#endif
2 changes: 2 additions & 0 deletions ios/FaceDetector/RNFaceEncoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#import "RNFaceEncoder.h"

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#define cDefaultFloatComparisonEpsilon 0.0001
#define cModEqualFloatsWithEpsilon(dividend, divisor, modulo, epsilon) \
fabs( fmod(dividend, divisor) - modulo ) < epsilon
Expand Down Expand Up @@ -117,3 +118,4 @@ - (CGFloat)radianAngleToDegrees:(CGFloat)angle
}

@end
#endif
19 changes: 16 additions & 3 deletions ios/RN/RNCamera.m
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ - (void)updateWhiteBalance
[device unlockForConfiguration];
}

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
- (void)updateFaceDetecting:(id)faceDetecting
{
[_faceDetectorManager setIsEnabled:faceDetecting];
Expand All @@ -303,6 +304,7 @@ - (void)updateFaceDetectionClassifications:(id)requestedClassifications
{
[_faceDetectorManager setClassificationsDetected:requestedClassifications];
}
#endif

- (void)takePicture:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
{
Expand Down Expand Up @@ -382,7 +384,9 @@ - (void)record:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve r
// At the time of writing AVCaptureMovieFileOutput and AVCaptureVideoDataOutput (> GMVDataOutput)
// cannot coexist on the same AVSession (see: https://stackoverflow.com/a/4986032/1123156).
// We stop face detection here and restart it in when AVCaptureMovieFileOutput finishes recording.
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
[_faceDetectorManager stopFaceDetection];
#endif
[self setupMovieFileCapture];
}

Expand Down Expand Up @@ -457,7 +461,9 @@ - (void)startSession
self.stillImageOutput = stillImageOutput;
}

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
[_faceDetectorManager maybeStartFaceDetectionOnSession:_session withPreviewLayer:_previewLayer];
#endif
[self setupOrDisableBarcodeScanner];

__weak RNCamera *weakSelf = self;
Expand All @@ -483,7 +489,9 @@ - (void)stopSession
return;
#endif
dispatch_async(self.sessionQueue, ^{
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
[_faceDetectorManager stopFaceDetection];
#endif
[self.previewLayer removeFromSuperlayer];
[self.session commitConfiguration];
[self.session stopRunning];
Expand Down Expand Up @@ -740,12 +748,15 @@ - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToO
self.videoRecordedResolve = nil;
self.videoRecordedReject = nil;
self.videoCodecType = nil;

[self cleanupMovieFileCapture];

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
// If face detection has been running prior to recording to file
// we reenable it here (see comment in -record).
[_faceDetectorManager maybeStartFaceDetectionOnSession:_session withPreviewLayer:_previewLayer];

#endif

if (self.session.sessionPreset != AVCaptureSessionPresetHigh) {
[self updateSessionPreset:AVCaptureSessionPresetHigh];
}
Expand All @@ -758,12 +769,14 @@ - (id)createFaceDetectorManager
Class faceDetectorManagerClass = NSClassFromString(@"RNFaceDetectorManager");
Class faceDetectorManagerStubClass = NSClassFromString(@"RNFaceDetectorManagerStub");

#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
if (faceDetectorManagerClass) {
return [[faceDetectorManagerClass alloc] initWithSessionQueue:_sessionQueue delegate:self];
} else if (faceDetectorManagerStubClass) {
return [[faceDetectorManagerStubClass alloc] init];
}

#endif

return nil;
}

Expand Down
4 changes: 4 additions & 0 deletions ios/RN/RNCameraManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,15 @@ + (NSDictionary *)validBarCodeTypes

+ (NSDictionary *)faceDetectorConstants
{
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#if __has_include("RNFaceDetectorManager.h")
return [RNFaceDetectorManager constants];
#else
return [RNFaceDetectorManagerStub constants];
#endif
#else
return [NSDictionary new];
#endif
}

RCT_CUSTOM_VIEW_PROPERTY(type, NSInteger, RNCamera)
Expand Down
12 changes: 6 additions & 6 deletions src/RNCamera.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ export default class Camera extends React.Component<PropsType> {
flashMode: CameraManager.FlashMode,
autoFocus: CameraManager.AutoFocus,
whiteBalance: CameraManager.WhiteBalance,
faceDetectionMode: CameraManager.FaceDetection.Mode,
faceDetectionLandmarks: CameraManager.FaceDetection.Landmarks,
faceDetectionClassifications: CameraManager.FaceDetection.Classifications,
faceDetectionMode: (CameraManager.FaceDetection || {}).Mode,
faceDetectionLandmarks: (CameraManager.FaceDetection || {}).Landmarks,
faceDetectionClassifications: (CameraManager.FaceDetection || {}).Classifications,
};

static propTypes = {
Expand Down Expand Up @@ -164,10 +164,10 @@ export default class Camera extends React.Component<PropsType> {
autoFocus: CameraManager.AutoFocus.on,
flashMode: CameraManager.FlashMode.off,
whiteBalance: CameraManager.WhiteBalance.auto,
faceDetectionMode: CameraManager.FaceDetection.fast,
faceDetectionMode: (CameraManager.FaceDetection || {}).fast,
barCodeTypes: Object.values(CameraManager.BarCodeType),
faceDetectionLandmarks: CameraManager.FaceDetection.Landmarks.none,
faceDetectionClassifications: CameraManager.FaceDetection.Classifications.none,
faceDetectionLandmarks: ((CameraManager.FaceDetection || {}).Landmarks || {}).none,
faceDetectionClassifications: ((CameraManager.FaceDetection || {}).Classifications || {}).none,
permissionDialogTitle: '',
permissionDialogMessage: '',
notAuthorizedView: (
Expand Down