[iOS] Make GoogleMobileVision framework optional

This commit is contained in:
Bruno Lemos 2018-03-12 16:41:33 -03:00
parent f1094302c7
commit 5a408b70b7
No known key found for this signature in database
GPG Key ID: 56ECEA49AAC4CE9F
12 changed files with 57 additions and 37 deletions

View File

@ -84,35 +84,15 @@ 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 Steps
##### Face Detection Steps
Face Detecion is optional on iOS. If you want it, you are going to need to install Google Mobile Vision frameworks in your project, as mentioned in the next section.
##### No Face Detection steps
If you do not need it and do not want to install the GMV frameworks, open your app xcode project, on the Project Navigator, expand the RNCamera project, right click on the FaceDetector folder and delete it (move to trash, if you want). If you keep that folder and do not follow the GMV installation setps, your project will not compile.
If you want to make this automatic, you can add a postinstall script to your app `package.json`. Inside the `postinstall_project` there is a xcode project ready with the folder removed (we opened xcode, removed the folder from the project and copied the resulting project file). The post install script is:
```
#!/bin/bash
echo "Creating project without FaceDetector"
if [ -e node_modules/react-native-camera/ios/FaceDetector ] ; then
rm -rf node_modules/react-native-camera/ios/FaceDetector
fi
cp node_modules/react-native-camera/postinstall_project/projectWithoutFaceDetection.pbxproj node_modules/react-native-camera/ios/RNCamera.xcodeproj/project.pbxproj
```
And add something like this to the `scripts` section in your `package.json`:
*Note:* The face detection code is excluded by default for the **CocoaPods** installation.
```
"postinstall": "./scripts/post.sh",
```
##### Installing GMV frameworks
###### Installing GMV frameworks
GMV (Google Mobile Vision) is used for Face detection by the iOS RNCamera. You have to link the google frameworks to your project to successfully compile the RNCamera project.
1. If using **CocoaPods** modify the dependency towards `react-native-camera` in your
@ -150,7 +130,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.
@ -166,11 +146,15 @@ Google Symbol Utilities: https://www.gstatic.com/cpdc/dbffca986f6337f8-GoogleSym
```gradle
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
}
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

View File

@ -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;
@ -31,3 +35,4 @@
- (void)stopFaceDetection;
@end
#endif

View File

@ -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"
@ -272,3 +273,4 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
}
@end
#endif

View File

@ -6,7 +6,9 @@
//
#import <React/RCTBridgeModule.h>
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <GoogleMobileVision/GoogleMobileVision.h>
#endif
@interface RNFaceDetectorModule : NSObject <RCTBridgeModule>
@end

View File

@ -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"
@ -193,3 +194,4 @@ RCT_EXPORT_METHOD(detectFaces:(nonnull NSDictionary *)options
}
@end
#endif

View File

@ -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>
@ -33,3 +34,4 @@ typedef NS_ENUM(NSInteger, RNFaceDetectionClassifications) {
+ (CGAffineTransform)transformFromDeviceOutput:(GMVDataOutput *)dataOutput toInterfaceVideoOrientation:(AVCaptureVideoOrientation)interfaceVideoOrientation;
@end
#endif

View File

@ -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"
@ -75,3 +76,4 @@ NSString *const RNGMVDataOutputHeightKey = @"Height";
}
@end
#endif

View File

@ -6,6 +6,7 @@
//
#import <UIKit/UIKit.h>
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
#import <GoogleMobileVision/GoogleMobileVision.h>
@interface RNFaceEncoder : NSObject
@ -15,3 +16,4 @@
- (NSDictionary *)encode:(GMVFaceFeature *)face;
@end
#endif

View File

@ -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
@ -117,3 +118,4 @@ cModEqualFloatsWithEpsilon(dividend, divisor, modulo, cDefaultFloatComparisonEps
}
@end
#endif

View File

@ -284,6 +284,7 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
[device unlockForConfiguration];
}
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
- (void)updateFaceDetecting:(id)faceDetecting
{
[_faceDetectorManager setIsEnabled:faceDetecting];
@ -303,6 +304,7 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
{
[_faceDetectorManager setClassificationsDetected:requestedClassifications];
}
#endif
- (void)takePicture:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
{
@ -382,7 +384,9 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
// 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];
}
@ -443,7 +447,9 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
self.stillImageOutput = stillImageOutput;
}
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
[_faceDetectorManager maybeStartFaceDetectionOnSession:_session withPreviewLayer:_previewLayer];
#endif
[self setupOrDisableBarcodeScanner];
__weak RNCamera *weakSelf = self;
@ -469,7 +475,9 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
return;
#endif
dispatch_async(self.sessionQueue, ^{
#if __has_include(<GoogleMobileVision/GoogleMobileVision.h>)
[_faceDetectorManager stopFaceDetection];
#endif
[self.previewLayer removeFromSuperlayer];
[self.session commitConfiguration];
[self.session stopRunning];
@ -722,9 +730,12 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
self.videoRecordedReject = 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];
@ -738,11 +749,13 @@ static NSDictionary *defaultFaceDetectorOptions = nil;
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;
}

View File

@ -86,11 +86,15 @@ RCT_EXPORT_VIEW_PROPERTY(onFacesDetected, RCTDirectEventBlock);
+ (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)

View File

@ -106,9 +106,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 = {
@ -144,10 +144,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: (