merge with master
This commit is contained in:
commit
30af527ac3
|
@ -1,11 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import { Image, StatusBar, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||||
Image,
|
|
||||||
StatusBar,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
View,
|
|
||||||
} from 'react-native';
|
|
||||||
import Camera from 'react-native-camera';
|
import Camera from 'react-native-camera';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -68,37 +62,39 @@ export default class Example extends React.Component {
|
||||||
orientation: Camera.constants.Orientation.auto,
|
orientation: Camera.constants.Orientation.auto,
|
||||||
flashMode: Camera.constants.FlashMode.auto,
|
flashMode: Camera.constants.FlashMode.auto,
|
||||||
},
|
},
|
||||||
isRecording: false
|
isRecording: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
takePicture = () => {
|
takePicture = () => {
|
||||||
if (this.camera) {
|
if (this.camera) {
|
||||||
this.camera.capture()
|
this.camera
|
||||||
.then((data) => console.log(data))
|
.capture()
|
||||||
|
.then(data => console.log(data))
|
||||||
.catch(err => console.error(err));
|
.catch(err => console.error(err));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
startRecording = () => {
|
startRecording = () => {
|
||||||
if (this.camera) {
|
if (this.camera) {
|
||||||
this.camera.capture({mode: Camera.constants.CaptureMode.video})
|
this.camera
|
||||||
.then((data) => console.log(data))
|
.capture({ mode: Camera.constants.CaptureMode.video })
|
||||||
.catch(err => console.error(err));
|
.then(data => console.log(data))
|
||||||
|
.catch(err => console.error(err));
|
||||||
this.setState({
|
this.setState({
|
||||||
isRecording: true
|
isRecording: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
stopRecording = () => {
|
stopRecording = () => {
|
||||||
if (this.camera) {
|
if (this.camera) {
|
||||||
this.camera.stopCapture();
|
this.camera.stopCapture();
|
||||||
this.setState({
|
this.setState({
|
||||||
isRecording: false
|
isRecording: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
switchType = () => {
|
switchType = () => {
|
||||||
let newType;
|
let newType;
|
||||||
|
@ -116,7 +112,7 @@ export default class Example extends React.Component {
|
||||||
type: newType,
|
type: newType,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
get typeIcon() {
|
get typeIcon() {
|
||||||
let icon;
|
let icon;
|
||||||
|
@ -149,7 +145,7 @@ export default class Example extends React.Component {
|
||||||
flashMode: newFlashMode,
|
flashMode: newFlashMode,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
get flashIcon() {
|
get flashIcon() {
|
||||||
let icon;
|
let icon;
|
||||||
|
@ -169,12 +165,9 @@ export default class Example extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<StatusBar
|
<StatusBar animated hidden />
|
||||||
animated
|
|
||||||
hidden
|
|
||||||
/>
|
|
||||||
<Camera
|
<Camera
|
||||||
ref={(cam) => {
|
ref={cam => {
|
||||||
this.camera = cam;
|
this.camera = cam;
|
||||||
}}
|
}}
|
||||||
style={styles.preview}
|
style={styles.preview}
|
||||||
|
@ -186,62 +179,34 @@ export default class Example extends React.Component {
|
||||||
onZoomChanged={() => {}}
|
onZoomChanged={() => {}}
|
||||||
defaultTouchToFocus
|
defaultTouchToFocus
|
||||||
mirrorImage={false}
|
mirrorImage={false}
|
||||||
|
permissionDialogTitle="Sample title"
|
||||||
|
permissionDialogMessage="Sample dialog message"
|
||||||
/>
|
/>
|
||||||
<View style={[styles.overlay, styles.topOverlay]}>
|
<View style={[styles.overlay, styles.topOverlay]}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity style={styles.typeButton} onPress={this.switchType}>
|
||||||
style={styles.typeButton}
|
<Image source={this.typeIcon} />
|
||||||
onPress={this.switchType}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
source={this.typeIcon}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity
|
<TouchableOpacity style={styles.flashButton} onPress={this.switchFlash}>
|
||||||
style={styles.flashButton}
|
<Image source={this.flashIcon} />
|
||||||
onPress={this.switchFlash}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
source={this.flashIcon}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.overlay, styles.bottomOverlay]}>
|
<View style={[styles.overlay, styles.bottomOverlay]}>
|
||||||
{
|
{(!this.state.isRecording && (
|
||||||
!this.state.isRecording
|
<TouchableOpacity style={styles.captureButton} onPress={this.takePicture}>
|
||||||
&&
|
<Image source={require('./assets/ic_photo_camera_36pt.png')} />
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.captureButton}
|
|
||||||
onPress={this.takePicture}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
source={require('./assets/ic_photo_camera_36pt.png')}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
||
|
)) ||
|
||||||
null
|
null}
|
||||||
}
|
|
||||||
<View style={styles.buttonsSpace} />
|
<View style={styles.buttonsSpace} />
|
||||||
{
|
{(!this.state.isRecording && (
|
||||||
!this.state.isRecording
|
<TouchableOpacity style={styles.captureButton} onPress={this.startRecording}>
|
||||||
&&
|
<Image source={require('./assets/ic_videocam_36pt.png')} />
|
||||||
<TouchableOpacity
|
</TouchableOpacity>
|
||||||
style={styles.captureButton}
|
)) || (
|
||||||
onPress={this.startRecording}
|
<TouchableOpacity style={styles.captureButton} onPress={this.stopRecording}>
|
||||||
>
|
<Image source={require('./assets/ic_stop_36pt.png')} />
|
||||||
<Image
|
</TouchableOpacity>
|
||||||
source={require('./assets/ic_videocam_36pt.png')}
|
)}
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.captureButton}
|
|
||||||
onPress={this.stopRecording}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
source={require('./assets/ic_stop_36pt.png')}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
}
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||||
|
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="16"
|
android:minSdkVersion="16"
|
||||||
|
|
24
README.md
24
README.md
|
@ -34,7 +34,7 @@ To enable `video recording` feature you have to add the following code to the `A
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
1. JDK >= 1.7 (if you run on 1.6 you will get an error on "_cameras = new HashMap<>();")
|
1. JDK >= 1.7 (if you run on 1.6 you will get an error on "_cameras = new HashMap<>();")
|
||||||
2. With iOS 10 and higher you need to add the "Privacy - Camera Usage Description" key to the info.plist of your project. This should be found in 'your_project/ios/your_project/Info.plist'. Add the following code:
|
2. With iOS 10 and higher you need to add the "Privacy - Camera Usage Description" key to the Info.plist of your project. This should be found in 'your_project/ios/your_project/Info.plist'. Add the following code:
|
||||||
```
|
```
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>Your message to user when the camera is accessed for the first time</string>
|
<string>Your message to user when the camera is accessed for the first time</string>
|
||||||
|
@ -56,8 +56,6 @@ To enable `video recording` feature you have to add the following code to the `A
|
||||||
<string>Your message to user when the photo library is accessed for the first time</string>
|
<string>Your message to user when the photo library is accessed for the first time</string>
|
||||||
```
|
```
|
||||||
|
|
||||||
NSPhotoLibraryAddUsageDescription
|
|
||||||
|
|
||||||
### Mostly automatic install with react-native
|
### Mostly automatic install with react-native
|
||||||
1. `npm install react-native-camera --save`
|
1. `npm install react-native-camera --save`
|
||||||
3. `react-native link react-native-camera`
|
3. `react-native link react-native-camera`
|
||||||
|
@ -324,6 +322,26 @@ from javascript.
|
||||||
|
|
||||||
If set to `true`, the device will not sleep while the camera preview is visible. This mimics the behavior of the default camera app, which keeps the device awake while open.
|
If set to `true`, the device will not sleep while the camera preview is visible. This mimics the behavior of the default camera app, which keeps the device awake while open.
|
||||||
|
|
||||||
|
#### `Android` `permissionDialogTitle`
|
||||||
|
|
||||||
|
Starting on android M individual permissions must be granted for certain services, the camera is one of them, you can use this to change the title of the dialog prompt requesting permissions.
|
||||||
|
|
||||||
|
#### `Android` `permissionDialogMessage`
|
||||||
|
|
||||||
|
Starting on android M individual permissions must be granted for certain services, the camera is one of them, you can use this to change the content of the dialog prompt requesting permissions.
|
||||||
|
|
||||||
|
#### `notAuthorizedView`
|
||||||
|
|
||||||
|
By default a `Camera not authorized` message will be displayed when access to the camera has been denied, if set displays the passed react element instead of the default one.
|
||||||
|
|
||||||
|
#### `pendingAuthorizationView`
|
||||||
|
|
||||||
|
By default a <ActivityIndicator> will be displayed while the component is waiting for the user to grant/deny access to the camera, if set displays the passed react element instead of the default one.
|
||||||
|
|
||||||
|
#### `pendingAuthorizationView`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### `mirrorImage`
|
#### `mirrorImage`
|
||||||
|
|
||||||
If set to `true`, the image returned will be mirrored.
|
If set to `true`, the image returned will be mirrored.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
|
@ -9,6 +8,10 @@ import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
requireNativeComponent,
|
requireNativeComponent,
|
||||||
ViewPropTypes,
|
ViewPropTypes,
|
||||||
|
PermissionsAndroid,
|
||||||
|
ActivityIndicator,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
const CameraManager = NativeModules.CameraManager || NativeModules.CameraModule;
|
const CameraManager = NativeModules.CameraManager || NativeModules.CameraModule;
|
||||||
|
@ -92,6 +95,10 @@ export default class Camera extends Component {
|
||||||
playSoundOnCapture: PropTypes.bool,
|
playSoundOnCapture: PropTypes.bool,
|
||||||
torchMode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
torchMode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
type: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
type: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
permissionDialogTitle: PropTypes.string,
|
||||||
|
permissionDialogMessage: PropTypes.string,
|
||||||
|
notAuthorizedView: PropTypes.element,
|
||||||
|
pendingAuthorizationView: PropTypes.element,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -109,6 +116,37 @@ export default class Camera extends Component {
|
||||||
torchMode: CameraManager.TorchMode.off,
|
torchMode: CameraManager.TorchMode.off,
|
||||||
mirrorImage: false,
|
mirrorImage: false,
|
||||||
barCodeTypes: Object.values(CameraManager.BarCodeType),
|
barCodeTypes: Object.values(CameraManager.BarCodeType),
|
||||||
|
permissionDialogTitle: '',
|
||||||
|
permissionDialogMessage: '',
|
||||||
|
notAuthorizedView: (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Camera not authorized
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
pendingAuthorizationView: (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ActivityIndicator size="small" />
|
||||||
|
</View>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
static checkDeviceAuthorizationStatus = CameraManager.checkDeviceAuthorizationStatus;
|
static checkDeviceAuthorizationStatus = CameraManager.checkDeviceAuthorizationStatus;
|
||||||
|
@ -124,6 +162,7 @@ export default class Camera extends Component {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
isAuthorizationChecked: false,
|
||||||
isRecording: false,
|
isRecording: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -134,13 +173,28 @@ export default class Camera extends Component {
|
||||||
let { captureMode } = convertNativeProps({ captureMode: this.props.captureMode });
|
let { captureMode } = convertNativeProps({ captureMode: this.props.captureMode });
|
||||||
let hasVideoAndAudio =
|
let hasVideoAndAudio =
|
||||||
this.props.captureAudio && captureMode === Camera.constants.CaptureMode.video;
|
this.props.captureAudio && captureMode === Camera.constants.CaptureMode.video;
|
||||||
let check = hasVideoAndAudio
|
|
||||||
? Camera.checkDeviceAuthorizationStatus
|
|
||||||
: Camera.checkVideoAuthorizationStatus;
|
|
||||||
|
|
||||||
if (check) {
|
if (Platform.OS === 'ios') {
|
||||||
const isAuthorized = await check();
|
let check = hasVideoAndAudio
|
||||||
this.setState({ isAuthorized });
|
? Camera.checkDeviceAuthorizationStatus
|
||||||
|
: Camera.checkVideoAuthorizationStatus;
|
||||||
|
|
||||||
|
if (check) {
|
||||||
|
const isAuthorized = await check();
|
||||||
|
this.setState({ isAuthorized, isAuthorizationChecked: true });
|
||||||
|
}
|
||||||
|
} else if (Platform.OS === 'android') {
|
||||||
|
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA, {
|
||||||
|
title: this.props.permissionDialogTitle,
|
||||||
|
message: this.props.permissionDialogMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
isAuthorized: granted === PermissionsAndroid.RESULTS.GRANTED,
|
||||||
|
isAuthorizationChecked: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ isAuthorized: true, isAuthorizationChecked: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +236,13 @@ export default class Camera extends Component {
|
||||||
const style = [styles.base, this.props.style];
|
const style = [styles.base, this.props.style];
|
||||||
const nativeProps = convertNativeProps(this.props);
|
const nativeProps = convertNativeProps(this.props);
|
||||||
|
|
||||||
return <RCTCamera ref={CAMERA_REF} {...nativeProps} />;
|
if (this.state.isAuthorized) {
|
||||||
|
return <RCTCamera ref={CAMERA_REF} {...nativeProps} />;
|
||||||
|
} else if (!this.state.isAuthorizationChecked) {
|
||||||
|
return this.props.pendingAuthorizationView;
|
||||||
|
} else {
|
||||||
|
return this.props.notAuthorizedView;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onBarCodeRead = data => {
|
_onBarCodeRead = data => {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import Camera from './Camera';
|
import Camera from './Camera';
|
||||||
export RNCamera from './RNCamera';
|
import RNCamera from './RNCamera';
|
||||||
export FaceDetector from './FaceDetector';
|
import FaceDetector from './FaceDetector';
|
||||||
|
|
||||||
|
export { RNCamera, FaceDetector };
|
||||||
|
|
||||||
export default Camera;
|
export default Camera;
|
||||||
|
|
Loading…
Reference in New Issue