Skip to content

Instantly share code, notes, and snippets.

@pvanliefland
Created June 7, 2017 14:33
Show Gist options
  • Save pvanliefland/8c2522a27daf4759b015e3345ba47dda to your computer and use it in GitHub Desktop.
Save pvanliefland/8c2522a27daf4759b015e3345ba47dda to your computer and use it in GitHub Desktop.
react-native-camera (workarounds)
import React from 'react';
import {Platform, PermissionsAndroid, View} from 'react-native';
import RNCamera from 'react-native-camera';
/**
* Overridden Camera module
*
* 3 goals:
* - handle Android permissions (https://github.com/lwansbrough/react-native-camera/issues/224 as well as
* https://github.com/lwansbrough/react-native-camera/issues/671)
* - fix https://github.com/lwansbrough/react-native-camera/issues/604
* - add a "onPermissions" callback informing the parent element of permissions state
*
* Additional props:
* - onPermissions: called with true or false
*/
export default class Camera extends RNCamera {
// react-native-camera does not handle the new Android permissions system, so we overrides the static checkXYZ()
// functions (see implementation below)
static checkDeviceAuthorizationStatus = Platform.OS === 'ios' ?
RNCamera.checkDeviceAuthorizationStatus :
checkDeviceAuthorizationStatusAndroid;
static checkVideoAuthorizationStatus = Platform.OS === 'ios' ?
RNCamera.checkVideoAuthorizationStatus :
checkVideoAuthorizationStatusAndroid;
static checkAudioAuthorizationStatus = Platform.OS === 'ios' ?
RNCamera.checkAudioAuthorizationStatus :
checkAudioAuthorizationStatusAndroid;
/**
* Overrides react-native camera Camera.componentWillMount
*
*/
async componentWillMount() {
this._addOnBarCodeReadListener();
const captureMode = typeof this.props.captureMode === 'string' ?
RNCamera.constants.CaptureMode[this.props.captureMode] :
this.props.captureMode;
const hasVideoAndAudio = this.props.captureAudio && captureMode === RNCamera.constants.CaptureMode.video;
const check = hasVideoAndAudio ? Camera.checkDeviceAuthorizationStatus : Camera.checkVideoAuthorizationStatus;
if (check) {
const isAuthorized = await check();
if (isAuthorized) {
this.props.onPermissions(true);
this.setState({isAuthorized});
}
else if (Platform.OS === 'android') {
const permissionSet = hasVideoAndAudio ?
[PermissionsAndroid.PERMISSIONS.CAMERA, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO] :
[PermissionsAndroid.PERMISSIONS.CAMERA];
PermissionsAndroid
.requestMultiple(permissionSet)
.then(results => {
const denied = Object.values(results).some(value => value !== 'granted');
this.setState({isAuthorized: !denied});
this.props.onPermissions(!denied);
})
.done();
}
else { // iOS
this.props.onPermissions(false);
this.setState({isAuthorized});
}
}
}
/**
* Override render - we want to avoid rendering the component itself before getting permissions info for 2 reasons:
* - https://github.com/lwansbrough/react-native-camera/issues/604
* - on Android, if directly rendering the component, it doesn't get refreshed just after granting the permissions
*
* @returns {XML}
*/
render() {
return this.state.isAuthorized ? super.render() : <View style={this.props.style}/>
}
}
Camera.propTypes = {
...RNCamera.propTypes, ...{
onPermissions: React.PropTypes.func
}
};
Camera.defaultProps = {
...RNCamera.defaultProps, ...{
onPermissions: () => {
}
}
};
function checkAuthorizationStatusAndroid(permissionSet) {
const androidPermissionPromises = permissionSet.map(PermissionsAndroid.check);
return new Promise((resolve, reject) => {
Promise
.all(androidPermissionPromises)
.then(results => {
resolve(results.indexOf(false) === -1);
})
.catch(reject)
.done();
});
}
function checkDeviceAuthorizationStatusAndroid() {
return checkAuthorizationStatusAndroid([
PermissionsAndroid.PERMISSIONS.CAMERA, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO
]);
}
function checkVideoAuthorizationStatusAndroid() {
return checkAuthorizationStatusAndroid([PermissionsAndroid.PERMISSIONS.CAMERA]);
}
function checkAudioAuthorizationStatusAndroid() {
return checkAuthorizationStatusAndroid([PermissionsAndroid.PERMISSIONS.RECORD_AUDIO]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment