У меня есть проект, который использует библиотеку React Native Camera, а также CameraRoll из vanilla React Native. Когда я открываю приложение, приложение запрашивает разрешения камеры, но я не знаю, почему. Это только потому, что я указал это в своем AndroidManifest.xml?
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
package = "com.gradualcamera">
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name = "android.permission.CAMERA" />
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name = ".MainApplication"
android:label = "@string/app_name"
android:icon = "@mipmap/ic_launcher"
android:roundIcon = "@mipmap/ic_launcher_round"
android:allowBackup = "false"
android:theme = "@style/AppTheme">
<activity
android:name = ".MainActivity"
android:label = "@string/app_name"
android:configChanges = "keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode = "adjustResize">
<intent-filter>
<action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name = "com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Почему при использовании React Native Camera мне не нужно запрашивать разрешения, но когда я использую CameraRoll, разрешения не предоставляются по умолчанию, и мне приходится использовать библиотеку React Native Permissions.
Я спрашиваю об этом, потому что хочу запросить эти разрешения сразу, когда пользователь открывает приложение, и это сложно реализовать, поскольку я не знаю, где запрашиваются разрешения. Сейчас пользователь получает запросы на камеру «по умолчанию», но не на хранилище. Почему это?
import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native'
import { RNCamera } from 'react-native-camera'
import { CameraRoll } from 'react-native'
import Permissions from 'react-native-permissions'
import ActionButton from 'react-native-action-button'
import Icon from 'react-native-vector-icons/Ionicons'
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
button: {
height: 200,
justifyContent: 'flex-end',
alignItems: 'center'
},
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white',
},
});
export default class Cam extends Component {
constructor() {
super()
this.takePicture = this.takePicture.bind(this)
}
takePicture = async function() {
if (this.camera) {
const options = { quality: 0.5, base64: true }
const data = await this.camera.takePictureAsync(options)
CameraRoll.saveToCameraRoll(data.uri)
}
}
render() {
return (
<View style = {styles.container}>
<RNCamera
ref = {ref => {this.camera = ref}}
style = {{
flex: 1,
width: '100%',
position: 'relative'
}}
>
</RNCamera>
<ActionButton size = {80} useNativeFeedback = {false} buttonColor = "rgba(231,76,60,1)">
<ActionButton.Item useNativeFeedback = {false} buttonColor='#9b59b6' title = "Settings" onPress = {this.props.switchScreen}>
<Icon name = "md-create" style = {styles.actionButtonIcon} />
</ActionButton.Item>
<ActionButton.Item useNativeFeedback = {false} buttonColor='#1abc9c' title = "Start" onPress = {this.takePicture}>
<Icon name = "md-done-all" style = {styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
</View>
)
}
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это потому, что вы вызываете реакцию на собственную камеру в методе рендеринга:
<RNCamera
ref = {ref => {this.camera = ref}}
style = {{
flex: 1,
width: '100%',
position: 'relative'
}}
>
</RNCamera>
Чтобы решить эту проблему, я использовал тернарный оператор и состояние:
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import { RNCamera } from 'react-native-camera';
import { CameraRoll } from 'react-native';
import Permissions from 'react-native-permissions';
import ActionButton from 'react-native-action-button';
import Icon from 'react-native-vector-icons/Ionicons';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
button: {
height: 200,
justifyContent: 'flex-end',
alignItems: 'center'
},
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white'
}
});
export default class Cam extends Component {
constructor(props) {
super(props);
this.state = {
takePicture: false
};
}
takePicture = async () => {
console.info('function was called');
await this.setState({ takePicture: true });
// if (this.camera) {
// const options = { quality: 0.5, base64: true };
// const data = await this.camera.takePictureAsync(options);
// CameraRoll.saveToCameraRoll(data.uri);
// }
};
render() {
return (
<View style = {styles.container}>
{this.state.takePicture ? (
<RNCamera
ref = {ref => {
this.camera = ref;
}}
style = {{
flex: 1,
width: '100%',
position: 'relative'
}}
/>
) : null}
<ActionButton size = {80} useNativeFeedback = {false} buttonColor = "rgba(231,76,60,1)">
<ActionButton.Item useNativeFeedback = {false} buttonColor = "#9b59b6" title = "Settings">
<Icon name = "md-create" style = {styles.actionButtonIcon} />
</ActionButton.Item>
<ActionButton.Item useNativeFeedback = {false} buttonColor = "#1abc9c" title = "Start" onPress = {this.takePicture}>
<Icon name = "md-done-all" style = {styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
</View>
);
}
}
Также для хранения вам не нужно запрашивать разрешения, вам просто нужно написать разрешения на хранение в XML-файле Android. Собственная камера React и Camera Roll запрашивают разрешение по-разному, потому что они сделали библиотеку только такой. Если вы хотите запросить все разрешения одновременно в начале, вы можете использовать собственные разрешения и получить все разрешения, которые вы хотите в начале (возможно, в компоненте заставки, если он у вас есть). Затем, когда вы позже будете использовать реагирующую нативную камеру, она больше не будет запрашивать разрешения.