Merge pull request #1076 from react-native-community/android-6-permissions

Add permission handling for android 6+
This commit is contained in:
Oscar Franco 2018-01-07 08:56:14 +01:00 committed by GitHub
commit 4e237549e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 9 deletions

View File

@ -186,6 +186,8 @@ 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

View File

@ -322,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.

View File

@ -8,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;
@ -91,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 = {
@ -108,6 +116,31 @@ 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;
@ -123,6 +156,7 @@ export default class Camera extends Component {
super(); super();
this.state = { this.state = {
isAuthorized: false, isAuthorized: false,
isAuthorizationChecked: false,
isRecording: false, isRecording: false,
}; };
} }
@ -131,16 +165,31 @@ export default class Camera extends Component {
this._addOnBarCodeReadListener(); this._addOnBarCodeReadListener();
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 if (Platform.OS === 'ios') {
? Camera.checkDeviceAuthorizationStatus
: Camera.checkVideoAuthorizationStatus; let check = hasVideoAndAudio ? Camera.checkDeviceAuthorizationStatus : Camera.checkVideoAuthorizationStatus;
if (check) { if (check) {
const isAuthorized = await check(); const isAuthorized = await check();
this.setState({ isAuthorized }); 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 })
}
} }
componentWillUnmount() { componentWillUnmount() {
@ -181,7 +230,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);
if(this.state.isAuthorized) {
return <RCTCamera ref={CAMERA_REF} {...nativeProps} />; return <RCTCamera ref={CAMERA_REF} {...nativeProps} />;
} else if (!this.state.isAuthorizationChecked) {
return this.props.pendingAuthorizationView
} else {
return this.props.notAuthorizedView
}
} }
_onBarCodeRead = data => { _onBarCodeRead = data => {